@@ -9,11 +9,15 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
9
9
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" ;
10
10
import {
11
11
CallToolRequestSchema ,
12
- type CallToolResult ,
12
+ ListResourceTemplatesRequestSchema ,
13
+ ListResourcesRequestSchema ,
13
14
ListToolsRequestSchema ,
15
+ ReadResourceRequestSchema ,
16
+ type Resource ,
17
+ type ResourceTemplate ,
14
18
type Tool ,
15
19
} from "@modelcontextprotocol/sdk/types.js" ;
16
- import { Zodios , type ZodiosInstance , isErrorFromAlias } from "@zodios/core" ;
20
+ import { Zodios , type ZodiosInstance } from "@zodios/core" ;
17
21
import { ApiDefinition } from "./types.js" ;
18
22
19
23
const { values } = parseArgs ( {
@@ -44,6 +48,8 @@ class DrupalMcpServer {
44
48
private readonly server : Server ;
45
49
private readonly api : ZodiosInstance < typeof ApiDefinition > ;
46
50
private _tools : Array < Tool > = [ ] ;
51
+ private _resourceTemplates : Array < ResourceTemplate > = [ ] ;
52
+ private _resources : Array < Resource > = [ ] ;
47
53
48
54
constructor ( ) {
49
55
this . server = new Server (
@@ -54,60 +60,66 @@ class DrupalMcpServer {
54
60
{
55
61
capabilities : {
56
62
tools : { } ,
63
+ resources : { } ,
57
64
} ,
58
65
} ,
59
66
) ;
60
67
61
68
this . api = new Zodios ( DRUPAL_BASE_URL as string , ApiDefinition ) ;
62
69
}
63
70
71
+ private setupResourceHandlers ( ) : void {
72
+ if ( this . _resourceTemplates . length > 0 ) {
73
+ console . error ( this . _resourceTemplates ) ;
74
+
75
+ this . server . setRequestHandler (
76
+ ListResourceTemplatesRequestSchema ,
77
+ async ( ) => ( {
78
+ resourceTemplates : this . _resourceTemplates ,
79
+ } ) ,
80
+ ) ;
81
+ }
82
+ if ( this . _resources . length > 0 ) {
83
+ this . server . setRequestHandler ( ListResourcesRequestSchema , async ( ) => ( {
84
+ resources : this . _resources ,
85
+ } ) ) ;
86
+ }
87
+
88
+ this . server . setRequestHandler (
89
+ ReadResourceRequestSchema ,
90
+ async ( request ) => {
91
+ const response = await this . api . post ( "/mcp/post" , {
92
+ jsonrpc : "2.0" ,
93
+ id : 2 ,
94
+ method : "resources/read" ,
95
+ params : {
96
+ uri : request . params . uri ,
97
+ } ,
98
+ } ) ;
99
+
100
+ return response . result ;
101
+ } ,
102
+ ) ;
103
+ }
104
+
64
105
private setupToolHandlers ( ) : void {
65
106
this . server . setRequestHandler ( ListToolsRequestSchema , async ( ) => ( {
66
107
tools : this . _tools ,
67
108
} ) ) ;
68
109
69
110
this . server . setRequestHandler ( CallToolRequestSchema , async ( request ) => {
70
- if (
71
- this . _tools . length === 0 ||
72
- ! this . _tools . find ( ( t ) => t . name === request . params . name )
73
- ) {
74
- return {
75
- content : {
76
- mimeType : "text/plain" ,
77
- text : `Tool "${ request . params . name } " not found` ,
78
- } ,
79
- isError : true ,
80
- } ;
81
- }
82
-
83
- try {
84
- const response = await this . api . executeTool ( request . params . arguments , {
85
- params : {
86
- toolId : request . params . name ,
87
- } ,
88
- } ) ;
111
+ const response = await this . api . post ( "/mcp/post" , {
112
+ jsonrpc : "2.0" ,
113
+ id : 2 ,
114
+ method : "tools/call" ,
115
+ params : {
116
+ name : request . params . name ,
117
+ arguments : request . params . arguments ,
118
+ } ,
119
+ } ) ;
120
+ console . error ( response . result ) ;
89
121
90
- return {
91
- content : [
92
- {
93
- type : "text" ,
94
- text : JSON . stringify ( response , null , 2 ) ,
95
- } ,
96
- ] ,
97
- } satisfies CallToolResult ;
98
- } catch ( error ) {
99
- if ( isErrorFromAlias ( ApiDefinition , "executeTool" , error ) ) {
100
- return {
101
- content : {
102
- mimeType : "text/plain" ,
103
- text : `Drupal API error: ${ error . message } ` ,
104
- } ,
105
- isError : true ,
106
- } ;
107
- }
108
-
109
- throw error ;
110
- }
122
+ return response . result ;
111
123
} ) ;
112
124
}
113
125
@@ -124,26 +136,39 @@ class DrupalMcpServer {
124
136
}
125
137
126
138
async init ( ) {
127
- try {
128
- const initInfo = await this . api . getInitializationInfo ( ) ;
129
- this . _tools = initInfo . tools ;
130
-
131
- if ( this . _tools . length > 0 ) {
132
- this . setupToolHandlers ( ) ;
133
- }
134
-
135
- this . setupErrorHandling ( ) ;
139
+ const [ tools , resourceTemplates , resources ] = await Promise . all ( [
140
+ this . api . post ( "/mcp/post" , {
141
+ jsonrpc : "2.0" ,
142
+ id : 0 ,
143
+ method : "tools/list" ,
144
+ } ) ,
145
+ this . api . post ( "/mcp/post" , {
146
+ jsonrpc : "2.0" ,
147
+ id : 1 ,
148
+ method : "resources/templates/list" ,
149
+ } ) ,
150
+ this . api . post ( "/mcp/post" , {
151
+ jsonrpc : "2.0" ,
152
+ id : 2 ,
153
+ method : "resources/list" ,
154
+ } ) ,
155
+ ] ) ;
156
+
157
+ this . _tools = tools . result . tools ;
158
+ this . _resourceTemplates = resourceTemplates . result . resourceTemplates ;
159
+ this . _resources = resources . result . resources ;
160
+
161
+ if ( this . _tools . length > 0 ) {
162
+ this . setupToolHandlers ( ) ;
163
+ }
136
164
137
- return this ;
138
- } catch ( error ) {
139
- if ( isErrorFromAlias ( ApiDefinition , "getInitializationInfo" , error ) ) {
140
- console . error ( `Drupal API error: ${ error . message } ` ) ;
165
+ if ( this . _resourceTemplates . length > 0 || this . _resources . length > 0 ) {
166
+ this . setupResourceHandlers ( ) ;
167
+ }
141
168
142
- process . exit ( 1 ) ;
143
- }
169
+ this . setupErrorHandling ( ) ;
144
170
145
- throw error ;
146
- }
171
+ return this ;
147
172
}
148
173
149
174
async run ( ) {
0 commit comments