@jalpp/mcp-adapter 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,25 +1,37 @@
1
- # mcp-adapter
1
+ # @jalpp/mcp-adapter
2
2
 
3
- Lightweight adapter utilities for registering tools on an [MCP](https://modelcontextprotocol.io) server with full TypeScript type safety.
3
+ Lightweight adapter utilities for registering tools on an [MCP](https://modelcontextprotocol.io) server with full TypeScript type safety. Supports manual tool registration and automatic HTTP endpoint-to-tool bridging with built-in auth.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install mcp-adapter
8
+ npm install @jalpp/mcp-adapter
9
9
  ```
10
10
 
11
- > **Peer dependency:** `@modelcontextprotocol/sdk >= 1.0.0` must be installed in your project.
11
+ **Peer dependencies** install these in your project if not already present:
12
12
 
13
- ## Usage
13
+ ```bash
14
+ npm install @modelcontextprotocol/sdk zod axios
15
+ ```
16
+
17
+ ## Adapters
18
+
19
+ | Adapter | Description |
20
+ |---------|-------------|
21
+ | `toolAdapter` | Register a tool with a typed callback |
22
+ | `toolContentAdapter` | Normalize a result into a `CallToolResult` |
23
+ | `httpToolAdapter` | Register an HTTP endpoint directly as a tool |
14
24
 
15
- ### `toolAdapter`
25
+ ---
26
+
27
+ ## `toolAdapter`
16
28
 
17
29
  Registers a typed tool on an `McpServer`. Input schema types flow through to the callback automatically — no manual type annotations needed.
18
30
 
19
31
  **With input schema:**
20
32
 
21
33
  ```ts
22
- import { toolAdapter, toolContentAdapter } from "mcp-adapter";
34
+ import { toolAdapter, toolContentAdapter } from "@jalpp/mcp-adapter";
23
35
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
24
36
  import z from "zod";
25
37
 
@@ -57,12 +69,14 @@ toolAdapter(server, {
57
69
  });
58
70
  ```
59
71
 
60
- ### `toolContentAdapter`
72
+ ---
73
+
74
+ ## `toolContentAdapter`
61
75
 
62
- Normalizes a service result into a `CallToolResult`. If `error` is defined it takes priority; otherwise `data` is pretty-printed as JSON.
76
+ Normalizes a service result into a `CallToolResult` text block. If `error` is defined it takes priority; otherwise `data` is serialized as pretty-printed JSON.
63
77
 
64
78
  ```ts
65
- import { toolContentAdapter } from "mcp-adapter";
79
+ import { toolContentAdapter } from "@jalpp/mcp-adapter";
66
80
 
67
81
  return toolContentAdapter(data ?? {}, error);
68
82
  ```
@@ -70,21 +84,136 @@ return toolContentAdapter(data ?? {}, error);
70
84
  | Argument | Type | Description |
71
85
  |----------|------|-------------|
72
86
  | `data` | `object` | Successful result payload |
73
- | `error` | `string \| undefined` | Error message — takes priority over `data` |
87
+ | `error` | `string \| undefined` | Error message — takes priority over `data` when present |
88
+
89
+ ---
90
+
91
+ ## `httpToolAdapter`
92
+
93
+ Registers an HTTP endpoint directly as an MCP tool. Handles the full request lifecycle — auth headers, query params vs request body, and error mapping — so you only need to declare the tool metadata and schema.
94
+
95
+ - **GET** requests map input args to **query parameters**
96
+ - **POST / PUT / PATCH / DELETE** map input args to the **JSON request body**
97
+
98
+ **With input schema:**
99
+
100
+ ```ts
101
+ import { httpToolAdapter } from "@jalpp/mcp-adapter";
102
+ import z from "zod";
103
+
104
+ httpToolAdapter(server, {
105
+ name: "get-analysis",
106
+ description: "Fetch position analysis from external API",
107
+ endpoint: "https://api.example.com/analyze",
108
+ method: "POST",
109
+ inputSchema: {
110
+ fen: z.string().describe("FEN string"),
111
+ depth: z.number().min(1).max(20),
112
+ },
113
+ auth: {
114
+ type: "bearer",
115
+ token: process.env.API_TOKEN!,
116
+ },
117
+ });
118
+ ```
119
+
120
+ **Without input schema:**
121
+
122
+ ```ts
123
+ httpToolAdapter(server, {
124
+ name: "get-server-status",
125
+ description: "Fetch API health status",
126
+ endpoint: "https://api.example.com/status",
127
+ method: "GET",
128
+ });
129
+ ```
130
+
131
+ ### Authentication
132
+
133
+ Three auth strategies are supported, all passed via the `auth` field:
74
134
 
75
- ## API
135
+ **Bearer token** — sends `Authorization: Bearer <token>`:
136
+
137
+ ```ts
138
+ auth: {
139
+ type: "bearer",
140
+ token: process.env.API_TOKEN!,
141
+ }
142
+ ```
143
+
144
+ **API key** — sends the key in a custom header:
145
+
146
+ ```ts
147
+ auth: {
148
+ type: "apikey",
149
+ header: "X-API-Key",
150
+ key: process.env.API_KEY!,
151
+ }
152
+ ```
153
+
154
+ **Basic auth** — sends `Authorization: Basic <base64(username:password)>`:
155
+
156
+ ```ts
157
+ auth: {
158
+ type: "basic",
159
+ username: "myuser",
160
+ password: process.env.PASSWORD!,
161
+ }
162
+ ```
163
+
164
+ ### Extra axios config
165
+
166
+ Pass any additional [axios request config](https://axios-http.com/docs/req_config) via `axiosConfig`:
167
+
168
+ ```ts
169
+ httpToolAdapter(server, {
170
+ name: "get-data",
171
+ description: "Fetch with custom timeout",
172
+ endpoint: "https://api.example.com/data",
173
+ method: "GET",
174
+ axiosConfig: {
175
+ timeout: 5000,
176
+ headers: { "Accept-Language": "en" },
177
+ },
178
+ });
179
+ ```
180
+
181
+ ---
182
+
183
+ ## API Reference
76
184
 
77
185
  ### `toolAdapter(server, adapter)`
78
186
 
79
- | Overload | Description |
187
+ | Overload | When to use |
80
188
  |----------|-------------|
81
- | `toolAdapter<T>(server, ToolInputAdapterWithSchema<T>)` | Tool with typed input schema |
82
- | `toolAdapter(server, ToolInputAdapterWithoutSchema)` | Tool with no input arguments |
189
+ | `toolAdapter<T>(server, ToolInputAdapterWithSchema<T>)` | Tool that receives typed input args |
190
+ | `toolAdapter(server, ToolInputAdapterWithoutSchema)` | Tool that takes no input |
83
191
 
84
192
  ### `toolContentAdapter(data, error)`
85
193
 
86
194
  Returns a `CallToolResult` with a single `text` content block.
87
195
 
196
+ ### `httpToolAdapter(server, adapter)`
197
+
198
+ | Overload | When to use |
199
+ |----------|-------------|
200
+ | `httpToolAdapter<T>(server, HttpToolAdapterWithSchema<T>)` | Endpoint that receives typed input args |
201
+ | `httpToolAdapter(server, HttpToolAdapterWithoutSchema)` | Endpoint that takes no input |
202
+
203
+ ### Auth types
204
+
205
+ | Type | Interface | Fields |
206
+ |------|-----------|--------|
207
+ | Bearer | `BearerAuth` | `token` |
208
+ | API Key | `ApiKeyAuth` | `header`, `key` |
209
+ | Basic | `BasicAuth` | `username`, `password` |
210
+
211
+ ---
212
+
213
+ ## Repository
214
+
215
+ [github.com/jalpp/mcp-adapter](https://github.com/jalpp/mcp-adapter)
216
+
88
217
  ## License
89
218
 
90
219
  MIT
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { McpServer, ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { ZodRawShapeCompat } from '@modelcontextprotocol/sdk/server/zod-compat.js';
3
3
  import { ToolAnnotations, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
4
+ import { AxiosRequestConfig } from 'axios';
4
5
 
5
6
  /**
6
7
  * Adapter input for registering a tool that declares an input schema.
@@ -92,4 +93,116 @@ declare function toolAdapter<T extends ZodRawShapeCompat>(server: McpServer, too
92
93
  */
93
94
  declare function toolAdapter(server: McpServer, toolInputAdapter: ToolInputAdapterWithoutSchema): void;
94
95
 
95
- export { toolAdapter, toolContentAdapter };
96
+ /**
97
+ * Supported HTTP methods for the HTTP tool adapter.
98
+ */
99
+ type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
100
+ /**
101
+ * API key authentication — sent as a request header.
102
+ * @example { type: "apikey", header: "X-API-Key", key: process.env.API_KEY! }
103
+ */
104
+ interface ApiKeyAuth {
105
+ type: "apikey";
106
+ /** Header name to send the key in (e.g. `"X-API-Key"`) */
107
+ header: string;
108
+ key: string;
109
+ }
110
+ /**
111
+ * Bearer token authentication — sends `Authorization: Bearer <token>`.
112
+ * @example { type: "bearer", token: process.env.API_TOKEN! }
113
+ */
114
+ interface BearerAuth {
115
+ type: "bearer";
116
+ token: string;
117
+ }
118
+ /**
119
+ * HTTP Basic authentication — sends `Authorization: Basic <base64>`.
120
+ * @example { type: "basic", username: "user", password: process.env.PASSWORD! }
121
+ */
122
+ interface BasicAuth {
123
+ type: "basic";
124
+ username: string;
125
+ password: string;
126
+ }
127
+ /**
128
+ * Union of all supported authentication strategies.
129
+ */
130
+ type HttpAuth = ApiKeyAuth | BearerAuth | BasicAuth;
131
+ /**
132
+ * Configuration for registering an HTTP endpoint as an MCP tool with an input schema.
133
+ *
134
+ * @template T - Zod raw shape inferred from `inputSchema`, typed through to the request.
135
+ */
136
+ interface HttpToolAdapterWithSchema<T extends ZodRawShapeCompat> {
137
+ /** Unique tool name in the MCP registry. */
138
+ name: string;
139
+ /** Description of the tool shown to the model. */
140
+ description: string;
141
+ /** Full URL of the API endpoint. */
142
+ endpoint: string;
143
+ /** HTTP method to use. GET maps args to query params; others map to request body. */
144
+ method: HttpMethod;
145
+ /** Zod shape defining the tool's input arguments. */
146
+ inputSchema: T;
147
+ /** Optional authentication strategy. */
148
+ auth?: HttpAuth;
149
+ /** Optional extra axios config (e.g. headers, timeout). */
150
+ axiosConfig?: AxiosRequestConfig;
151
+ }
152
+ /**
153
+ * Configuration for registering an HTTP endpoint as an MCP tool with no input arguments.
154
+ */
155
+ interface HttpToolAdapterWithoutSchema {
156
+ /** Unique tool name in the MCP registry. */
157
+ name: string;
158
+ /** Description of the tool shown to the model. */
159
+ description: string;
160
+ /** Full URL of the API endpoint. */
161
+ endpoint: string;
162
+ /** HTTP method to use. */
163
+ method: HttpMethod;
164
+ inputSchema?: undefined;
165
+ /** Optional authentication strategy. */
166
+ auth?: HttpAuth;
167
+ /** Optional extra axios config (e.g. headers, timeout). */
168
+ axiosConfig?: AxiosRequestConfig;
169
+ }
170
+ /**
171
+ * Registers an HTTP endpoint as an MCP tool with a typed input schema.
172
+ *
173
+ * GET requests map input args to query parameters.
174
+ * All other methods map input args to the JSON request body.
175
+ *
176
+ * @template T - Zod raw shape inferred from `inputSchema`.
177
+ * @param server - The `McpServer` instance to register the tool on.
178
+ * @param adapter - HTTP tool configuration including endpoint, method, schema, and auth.
179
+ *
180
+ * @example
181
+ * httpToolAdapter(server, {
182
+ * name: "get-analysis",
183
+ * description: "Fetch position analysis",
184
+ * endpoint: "https://api.example.com/analyze",
185
+ * method: "POST",
186
+ * inputSchema: { fen: z.string(), depth: z.number() },
187
+ * auth: { type: "bearer", token: process.env.API_TOKEN! },
188
+ * });
189
+ */
190
+ declare function httpToolAdapter<T extends ZodRawShapeCompat>(server: McpServer, adapter: HttpToolAdapterWithSchema<T>): void;
191
+ /**
192
+ * Registers an HTTP endpoint as an MCP tool with no input arguments.
193
+ *
194
+ * @param server - The `McpServer` instance to register the tool on.
195
+ * @param adapter - HTTP tool configuration including endpoint, method, and auth.
196
+ *
197
+ * @example
198
+ * httpToolAdapter(server, {
199
+ * name: "get-status",
200
+ * description: "Fetch API status",
201
+ * endpoint: "https://api.example.com/status",
202
+ * method: "GET",
203
+ * auth: { type: "apikey", header: "X-API-Key", key: process.env.API_KEY! },
204
+ * });
205
+ */
206
+ declare function httpToolAdapter(server: McpServer, adapter: HttpToolAdapterWithoutSchema): void;
207
+
208
+ export { type ApiKeyAuth, type BasicAuth, type BearerAuth, type HttpAuth, type HttpMethod, type HttpToolAdapterWithSchema, type HttpToolAdapterWithoutSchema, httpToolAdapter, toolAdapter, toolContentAdapter };
package/dist/index.js CHANGED
@@ -24,7 +24,81 @@ function toolAdapter(server, toolInputAdapter) {
24
24
  );
25
25
  }
26
26
  }
27
+
28
+ // src/axiosAdapter.ts
29
+ import axios from "axios";
30
+ function buildAuthHeaders(auth) {
31
+ switch (auth.type) {
32
+ case "apikey":
33
+ return { [auth.header]: auth.key };
34
+ case "bearer":
35
+ return { Authorization: `Bearer ${auth.token}` };
36
+ case "basic": {
37
+ const encoded = Buffer.from(`${auth.username}:${auth.password}`).toString("base64");
38
+ return { Authorization: `Basic ${encoded}` };
39
+ }
40
+ }
41
+ }
42
+ async function executeRequest(endpoint, method, args, auth, extraConfig) {
43
+ try {
44
+ const authHeaders = auth ? buildAuthHeaders(auth) : {};
45
+ const config = {
46
+ url: endpoint,
47
+ method,
48
+ headers: {
49
+ "Content-Type": "application/json",
50
+ ...authHeaders,
51
+ ...extraConfig?.headers
52
+ },
53
+ ...method === "GET" ? { params: args } : { data: args },
54
+ ...extraConfig
55
+ };
56
+ const response = await axios(config);
57
+ return { data: response.data };
58
+ } catch (err) {
59
+ if (axios.isAxiosError(err)) {
60
+ const status = err.response?.status ?? "unknown";
61
+ const message = err.response?.data?.message ?? err.message;
62
+ return { error: `HTTP ${status}: ${message}` };
63
+ }
64
+ return { error: `Unexpected error: ${String(err)}` };
65
+ }
66
+ }
67
+ function httpToolAdapter(server, adapter) {
68
+ if (adapter.inputSchema) {
69
+ const { endpoint, method, auth, axiosConfig, inputSchema } = adapter;
70
+ toolAdapter(server, {
71
+ name: adapter.name,
72
+ config: {
73
+ description: adapter.description,
74
+ inputSchema
75
+ },
76
+ cb: (async (args) => {
77
+ const { data, error } = await executeRequest(endpoint, method, args, auth, axiosConfig);
78
+ return toolContentAdapter(data ?? {}, error);
79
+ })
80
+ });
81
+ } else {
82
+ toolAdapter(server, {
83
+ name: adapter.name,
84
+ config: {
85
+ description: adapter.description
86
+ },
87
+ cb: async () => {
88
+ const { data, error } = await executeRequest(
89
+ adapter.endpoint,
90
+ adapter.method,
91
+ {},
92
+ adapter.auth,
93
+ adapter.axiosConfig
94
+ );
95
+ return toolContentAdapter(data ?? {}, error);
96
+ }
97
+ });
98
+ }
99
+ }
27
100
  export {
101
+ httpToolAdapter,
28
102
  toolAdapter,
29
103
  toolContentAdapter
30
104
  };
package/package.json CHANGED
@@ -1,12 +1,27 @@
1
1
  {
2
2
  "name": "@jalpp/mcp-adapter",
3
- "version": "0.1.2",
4
- "description": "Adapter utilities for registering MCP tools",
3
+ "version": "0.2.0",
4
+ "description": "Adapter utilities for registering MCP tools with full TypeScript type safety — supports typed callbacks and automatic HTTP endpoint bridging with auth",
5
5
  "author": "jalpp",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "mcp",
9
+ "model-context-protocol",
10
+ "adapter",
11
+ "llm",
12
+ "typescript",
13
+ "axios",
14
+ "http",
15
+ "tool"
16
+ ],
6
17
  "repository": {
7
18
  "type": "git",
8
19
  "url": "git+https://github.com/jalpp/mcp-adapter.git"
9
20
  },
21
+ "homepage": "https://github.com/jalpp/mcp-adapter#readme",
22
+ "bugs": {
23
+ "url": "https://github.com/jalpp/mcp-adapter/issues"
24
+ },
10
25
  "type": "module",
11
26
  "main": "./dist/index.js",
12
27
  "module": "./dist/index.js",
@@ -18,7 +33,9 @@
18
33
  }
19
34
  },
20
35
  "files": [
21
- "dist"
36
+ "dist",
37
+ "README.md",
38
+ "LICENSE"
22
39
  ],
23
40
  "scripts": {
24
41
  "build": "tsup",
@@ -27,13 +44,17 @@
27
44
  },
28
45
  "peerDependencies": {
29
46
  "@modelcontextprotocol/sdk": ">=1.0.0",
30
- "zod": ">=3.0.0"
47
+ "zod": ">=3.0.0",
48
+ "axios": ">=1.0.0"
31
49
  },
32
50
  "devDependencies": {
33
51
  "@modelcontextprotocol/sdk": ">=1.0.0",
34
- "zod": ">=3.0.0",
35
- "typescript": "^5.0.0",
52
+ "@types/node": "^20.0.0",
36
53
  "tsup": "^8.0.0",
37
- "@types/node": "^20.0.0"
54
+ "typescript": "^5.0.0",
55
+ "zod": ">=3.0.0"
56
+ },
57
+ "dependencies": {
58
+ "axios": "^1.13.6"
38
59
  }
39
60
  }