@tigerdata/mcp-boilerplate 0.9.0 → 0.9.2
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 +5 -5
- package/dist/cliEntrypoint.js +1 -1
- package/dist/eslintPlugin.js +8 -5
- package/dist/http/api.d.ts +2 -2
- package/dist/http/api.js +1 -1
- package/dist/http/mcp.d.ts +4 -3
- package/dist/http/mcp.js +14 -9
- package/dist/httpServer.d.ts +5 -5
- package/dist/httpServer.js +22 -7
- package/dist/index.d.ts +4 -5
- package/dist/index.js +3 -3
- package/dist/instrumentation.d.ts +2 -2
- package/dist/instrumentation.js +5 -5
- package/dist/logger.d.ts +1 -1
- package/dist/logger.js +1 -1
- package/dist/mcpServer.d.ts +4 -4
- package/dist/mcpServer.js +7 -4
- package/dist/stdio.d.ts +4 -4
- package/dist/tracing.d.ts +2 -2
- package/dist/types.d.ts +38 -16
- package/dist/types.spec.js +1 -1
- package/package.json +13 -16
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ This provides some common code for creating a [Model Context Protocol](https://m
|
|
|
14
14
|
2. Install dependencies:
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
|
|
17
|
+
./bun install
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
## Eslint Plugin
|
|
@@ -45,7 +45,7 @@ export default [
|
|
|
45
45
|
To build the TypeScript project:
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
|
-
|
|
48
|
+
./bun run build
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
This compiles the TypeScript files from `src/` to JavaScript in `dist/`.
|
|
@@ -55,7 +55,7 @@ This compiles the TypeScript files from `src/` to JavaScript in `dist/`.
|
|
|
55
55
|
To run TypeScript compilation in watch mode (rebuilds on file changes):
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
|
|
58
|
+
./bun run watch
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
### Linting
|
|
@@ -65,13 +65,13 @@ This project uses ESLint for code linting with TypeScript support.
|
|
|
65
65
|
To run the linter:
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
|
-
|
|
68
|
+
./bun run lint
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
To automatically fix linting issues where possible:
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
|
-
|
|
74
|
+
./bun run lint --write
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
### Continuous Integration
|
package/dist/cliEntrypoint.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
1
|
+
import { join } from 'node:path';
|
|
2
2
|
export async function cliEntrypoint(stdioEntrypoint, httpEntrypoint, instrumentation = join(import.meta.dir, './instrumentation.js')) {
|
|
3
3
|
// Parse command line arguments first
|
|
4
4
|
const args = process.argv.slice(2);
|
package/dist/eslintPlugin.js
CHANGED
|
@@ -34,11 +34,15 @@ const noOptionalInputSchema = {
|
|
|
34
34
|
VariableDeclarator(node) {
|
|
35
35
|
const varNode = node;
|
|
36
36
|
// Check if this variable has a TypeScript type annotation
|
|
37
|
-
if (varNode.id
|
|
38
|
-
|
|
37
|
+
if (varNode.id &&
|
|
38
|
+
varNode.id.typeAnnotation?.typeAnnotation) {
|
|
39
|
+
const typeAnn = varNode.id.typeAnnotation
|
|
40
|
+
?.typeAnnotation;
|
|
39
41
|
// Look for ApiFactory type reference
|
|
40
|
-
if (typeAnn
|
|
41
|
-
typeAnn.typeName
|
|
42
|
+
if (typeAnn?.type === 'TSTypeReference' &&
|
|
43
|
+
typeAnn.typeName &&
|
|
44
|
+
'name' in typeAnn.typeName &&
|
|
45
|
+
typeAnn.typeName.name === 'ApiFactory') {
|
|
42
46
|
// Get the type parameters
|
|
43
47
|
const typeParams = typeAnn.typeArguments?.params;
|
|
44
48
|
if (typeParams && typeParams.length >= 2) {
|
|
@@ -100,7 +104,6 @@ function isInsideApiFactoryInputSchema(node, context, apiFactoryInputSchemas) {
|
|
|
100
104
|
}
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
|
-
// Fallback: walk up parent chain if node.parent is available
|
|
104
107
|
let current = node.parent;
|
|
105
108
|
while (current) {
|
|
106
109
|
// Variable that's an ApiFactory input schema
|
package/dist/http/api.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* REST API alternative to MCP for direct use of the same tools.
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
export declare const apiRouterFactory: <Context extends Record<string, unknown>>(context: Context, apiFactories: readonly
|
|
4
|
+
import type { BaseApiFactory, RouterFactoryResult } from '../types.js';
|
|
5
|
+
export declare const apiRouterFactory: <Context extends Record<string, unknown>>(context: Context, apiFactories: readonly BaseApiFactory<Context>[]) => RouterFactoryResult;
|
package/dist/http/api.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* REST API alternative to MCP for direct use of the same tools.
|
|
3
3
|
*/
|
|
4
|
-
import { Router } from 'express';
|
|
5
4
|
import bodyParser from 'body-parser';
|
|
5
|
+
import { Router } from 'express';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
export const apiRouterFactory = (context, apiFactories) => {
|
|
8
8
|
const router = Router();
|
package/dist/http/mcp.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import {
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { McpFeatureFlags, RouterFactoryResult } from '../types.js';
|
|
3
3
|
export declare const mcpRouterFactory: <Context extends Record<string, unknown>>(context: Context, createServer: (context: Context, featureFlags: McpFeatureFlags) => {
|
|
4
4
|
server: McpServer;
|
|
5
|
-
}, { name, stateful, }?: {
|
|
5
|
+
}, { name, stateful, inspector, }?: {
|
|
6
6
|
name?: string;
|
|
7
7
|
stateful?: boolean;
|
|
8
|
+
inspector?: boolean;
|
|
8
9
|
}) => RouterFactoryResult;
|
package/dist/http/mcp.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
3
|
-
import {
|
|
3
|
+
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import { context as otelContext, propagation, SpanKind, SpanStatusCode, trace, } from '@opentelemetry/api';
|
|
4
5
|
import { ATTR_HTTP_RESPONSE_STATUS_CODE } from '@opentelemetry/semantic-conventions';
|
|
5
6
|
import { Router } from 'express';
|
|
6
|
-
import { randomUUID } from 'node:crypto';
|
|
7
7
|
import getRawBody from 'raw-body';
|
|
8
8
|
import { log } from '../logger.js';
|
|
9
9
|
const name = process.env.OTEL_SERVICE_NAME;
|
|
10
10
|
const tracer = trace.getTracer(name ? `${name}.router.mcp` : 'router.mcp');
|
|
11
|
-
export const mcpRouterFactory = (context, createServer, { name, stateful = true, } = {}) => {
|
|
11
|
+
export const mcpRouterFactory = (context, createServer, { name, stateful = true, inspector = false, } = {}) => {
|
|
12
12
|
const router = Router();
|
|
13
13
|
const transports = new Map();
|
|
14
14
|
const sessionFeatureFlags = new Map();
|
|
@@ -49,7 +49,8 @@ export const mcpRouterFactory = (context, createServer, { name, stateful = true,
|
|
|
49
49
|
let transport;
|
|
50
50
|
let body = req.body;
|
|
51
51
|
if (sessionId) {
|
|
52
|
-
|
|
52
|
+
const t = transports.get(sessionId);
|
|
53
|
+
if (!t) {
|
|
53
54
|
res.status(404).json({
|
|
54
55
|
jsonrpc: '2.0',
|
|
55
56
|
error: {
|
|
@@ -60,7 +61,7 @@ export const mcpRouterFactory = (context, createServer, { name, stateful = true,
|
|
|
60
61
|
});
|
|
61
62
|
return;
|
|
62
63
|
}
|
|
63
|
-
transport =
|
|
64
|
+
transport = t;
|
|
64
65
|
}
|
|
65
66
|
else {
|
|
66
67
|
if (!body) {
|
|
@@ -177,7 +178,7 @@ export const mcpRouterFactory = (context, createServer, { name, stateful = true,
|
|
|
177
178
|
});
|
|
178
179
|
return;
|
|
179
180
|
}
|
|
180
|
-
await transports.get(sessionId)
|
|
181
|
+
await transports.get(sessionId)?.handleRequest(req, res);
|
|
181
182
|
};
|
|
182
183
|
// Handle GET requests for server-to-client notifications via SSE
|
|
183
184
|
router.get('/', (req, res) => {
|
|
@@ -197,7 +198,11 @@ export const mcpRouterFactory = (context, createServer, { name, stateful = true,
|
|
|
197
198
|
<h1>${name}</h1>
|
|
198
199
|
<h2>Model Context Protocol (MCP) Server</h2>
|
|
199
200
|
<p>This endpoint is used for MCP communication. Please use an MCP-compatible client to interact with this server.</p>
|
|
200
|
-
|
|
201
|
+
${inspector
|
|
202
|
+
? `
|
|
203
|
+
<h3>Inspector</h3>
|
|
204
|
+
<p>You can use the <a href="/inspector">MCP Inspector</a> for testing purposes.</p>`
|
|
205
|
+
: ''}
|
|
201
206
|
<h3>Claude Code</h3>
|
|
202
207
|
<p>To connect to this MCP server using Claude Code, run the following command in your terminal:</p>
|
|
203
208
|
<pre><code>claude mcp add --transport http ${name || req.get('host')} ${fullUrl}</code></pre>
|
|
@@ -214,7 +219,7 @@ export const mcpRouterFactory = (context, createServer, { name, stateful = true,
|
|
|
214
219
|
for (const sessionId in transports) {
|
|
215
220
|
try {
|
|
216
221
|
log.info(`Closing transport for session ${sessionId}`);
|
|
217
|
-
await transports.get(sessionId)
|
|
222
|
+
await transports.get(sessionId)?.close();
|
|
218
223
|
transports.delete(sessionId);
|
|
219
224
|
}
|
|
220
225
|
catch (error) {
|
package/dist/httpServer.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import type { Server } from 'node:http';
|
|
2
3
|
import express from 'express';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Server } from 'node:http';
|
|
4
|
+
import { type AdditionalSetupArgs } from './mcpServer.js';
|
|
5
|
+
import type { BaseApiFactory, BasePromptFactory, ResourceFactory } from './types.js';
|
|
6
6
|
export declare const httpServerFactory: <Context extends Record<string, unknown>>({ name, version, context, apiFactories, promptFactories, resourceFactories, additionalSetup, cleanupFn, stateful, instructions, }: {
|
|
7
7
|
name: string;
|
|
8
8
|
version?: string;
|
|
9
9
|
context: Context;
|
|
10
|
-
apiFactories?: readonly
|
|
11
|
-
promptFactories?: readonly
|
|
10
|
+
apiFactories?: readonly BaseApiFactory<Context>[];
|
|
11
|
+
promptFactories?: readonly BasePromptFactory<Context>[];
|
|
12
12
|
resourceFactories?: readonly ResourceFactory<Context>[];
|
|
13
13
|
additionalSetup?: (args: AdditionalSetupArgs<Context>) => void;
|
|
14
14
|
cleanupFn?: () => void | Promise<void>;
|
package/dist/httpServer.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import bodyParser from 'body-parser';
|
|
2
3
|
import express from 'express';
|
|
3
|
-
import { mcpRouterFactory } from './http/mcp.js';
|
|
4
4
|
import { apiRouterFactory } from './http/api.js';
|
|
5
|
-
import {
|
|
6
|
-
import { mcpServerFactory } from './mcpServer.js';
|
|
5
|
+
import { mcpRouterFactory } from './http/mcp.js';
|
|
7
6
|
import { log } from './logger.js';
|
|
7
|
+
import { mcpServerFactory } from './mcpServer.js';
|
|
8
|
+
import { registerExitHandlers } from './registerExitHandlers.js';
|
|
8
9
|
import { StatusError } from './StatusError.js';
|
|
9
10
|
export const httpServerFactory = ({ name, version, context, apiFactories = [], promptFactories, resourceFactories, additionalSetup, cleanupFn, stateful = true, instructions, }) => {
|
|
10
11
|
const cleanupFns = cleanupFn
|
|
@@ -14,6 +15,9 @@ export const httpServerFactory = ({ name, version, context, apiFactories = [], p
|
|
|
14
15
|
log.info('Starting HTTP server...');
|
|
15
16
|
const app = express();
|
|
16
17
|
app.enable('trust proxy');
|
|
18
|
+
const PORT = process.env.PORT || 3001;
|
|
19
|
+
const inspector = process.env.NODE_ENV !== 'production' ||
|
|
20
|
+
['1', 'true'].includes(process.env.ENABLE_INSPECTOR ?? '0');
|
|
17
21
|
const [mcpRouter, mcpCleanup] = mcpRouterFactory(context, (context, featureFlags) => mcpServerFactory({
|
|
18
22
|
name,
|
|
19
23
|
version,
|
|
@@ -24,14 +28,14 @@ export const httpServerFactory = ({ name, version, context, apiFactories = [], p
|
|
|
24
28
|
additionalSetup,
|
|
25
29
|
featureFlags,
|
|
26
30
|
instructions,
|
|
27
|
-
}), { name, stateful });
|
|
31
|
+
}), { name, stateful, inspector });
|
|
28
32
|
cleanupFns.push(mcpCleanup);
|
|
29
33
|
app.use('/mcp', mcpRouter);
|
|
30
34
|
const [apiRouter, apiCleanup] = apiRouterFactory(context, apiFactories);
|
|
31
35
|
cleanupFns.push(apiCleanup);
|
|
32
36
|
app.use('/api', apiRouter);
|
|
33
37
|
// Error handler
|
|
34
|
-
app.use(
|
|
38
|
+
app.use((err, _req, res, _next) => {
|
|
35
39
|
if (err instanceof StatusError && err.status < 500) {
|
|
36
40
|
log.info('HTTP error response', {
|
|
37
41
|
message: err.message,
|
|
@@ -45,15 +49,26 @@ export const httpServerFactory = ({ name, version, context, apiFactories = [], p
|
|
|
45
49
|
.status(err instanceof StatusError ? err.status : 500)
|
|
46
50
|
.json({ error: err.message });
|
|
47
51
|
});
|
|
52
|
+
if (inspector) {
|
|
53
|
+
process.env.MCP_USE_ANONYMIZED_TELEMETRY = 'false';
|
|
54
|
+
import('@mcp-use/inspector')
|
|
55
|
+
.then(({ mountInspector }) => {
|
|
56
|
+
app.use(bodyParser.json());
|
|
57
|
+
mountInspector(app, { autoConnectUrl: `http://localhost:${PORT}/mcp` });
|
|
58
|
+
})
|
|
59
|
+
.catch(log.error);
|
|
60
|
+
}
|
|
48
61
|
// Start the server
|
|
49
|
-
const
|
|
50
|
-
const server = app.listen(PORT, (error) => {
|
|
62
|
+
const server = app.listen(PORT, async (error) => {
|
|
51
63
|
if (error) {
|
|
52
64
|
log.error('Error starting HTTP server:', error);
|
|
53
65
|
exitHandler(1);
|
|
54
66
|
}
|
|
55
67
|
else {
|
|
56
68
|
log.info(`HTTP Server listening on port ${PORT}`);
|
|
69
|
+
if (inspector) {
|
|
70
|
+
log.info(`🌐 MCP inspector running at http://localhost:${PORT}/inspector`);
|
|
71
|
+
}
|
|
57
72
|
}
|
|
58
73
|
});
|
|
59
74
|
cleanupFns.push(async () => {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
export { cliEntrypoint } from './cliEntrypoint.js';
|
|
2
2
|
export { httpServerFactory } from './httpServer.js';
|
|
3
3
|
export { log } from './logger.js';
|
|
4
|
-
export { stdioServerFactory } from './stdio.js';
|
|
5
|
-
export type { ApiFactory, McpFeatureFlags, PromptFactory, ResourceFactory, ParsedQs, } from './types.js';
|
|
6
|
-
export { StatusError } from './StatusError.js';
|
|
7
4
|
export type { AdditionalSetupArgs } from './mcpServer.js';
|
|
8
|
-
export { withSpan, addAiResultToSpan } from './tracing.js';
|
|
9
5
|
export { registerExitHandlers } from './registerExitHandlers.js';
|
|
10
|
-
export
|
|
6
|
+
export { StatusError } from './StatusError.js';
|
|
7
|
+
export { stdioServerFactory } from './stdio.js';
|
|
8
|
+
export { addAiResultToSpan, withSpan } from './tracing.js';
|
|
9
|
+
export type { ApiFactory, InferSchema, McpFeatureFlags, ParsedQs, PromptFactory, ResourceFactory, } from './types.js';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { cliEntrypoint } from './cliEntrypoint.js';
|
|
2
2
|
export { httpServerFactory } from './httpServer.js';
|
|
3
3
|
export { log } from './logger.js';
|
|
4
|
-
export { stdioServerFactory } from './stdio.js';
|
|
5
|
-
export { StatusError } from './StatusError.js';
|
|
6
|
-
export { withSpan, addAiResultToSpan } from './tracing.js';
|
|
7
4
|
export { registerExitHandlers } from './registerExitHandlers.js';
|
|
5
|
+
export { StatusError } from './StatusError.js';
|
|
6
|
+
export { stdioServerFactory } from './stdio.js';
|
|
7
|
+
export { addAiResultToSpan, withSpan } from './tracing.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { InstrumentationConfigMap } from '@opentelemetry/auto-instrumentations-node';
|
|
1
|
+
import { type InstrumentationConfigMap } from '@opentelemetry/auto-instrumentations-node';
|
|
3
2
|
import type { Instrumentation } from '@opentelemetry/instrumentation';
|
|
3
|
+
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
4
4
|
interface Options {
|
|
5
5
|
environment?: string;
|
|
6
6
|
instrumentations?: Instrumentation[];
|
package/dist/instrumentation.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { getNodeAutoInstrumentations, } from '@opentelemetry/auto-instrumentations-node';
|
|
2
|
+
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
|
|
3
3
|
import { OTLPTraceExporter as GrpcTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
|
|
4
4
|
import { OTLPTraceExporter as HttpTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
5
|
-
import {
|
|
6
|
-
import { BatchSpanProcessor, } from '@opentelemetry/sdk-trace-base';
|
|
5
|
+
import { resourceFromAttributes } from '@opentelemetry/resources';
|
|
7
6
|
import { BatchLogRecordProcessor, } from '@opentelemetry/sdk-logs';
|
|
8
|
-
import {
|
|
7
|
+
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
8
|
+
import { BatchSpanProcessor, } from '@opentelemetry/sdk-trace-base';
|
|
9
9
|
import { log } from './logger.js';
|
|
10
10
|
export const instrument = (options = {}) => {
|
|
11
11
|
const spanProcessors = [];
|
package/dist/logger.d.ts
CHANGED
package/dist/logger.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { logs, SeverityNumber } from '@opentelemetry/api-logs';
|
|
1
|
+
import { logs, SeverityNumber, } from '@opentelemetry/api-logs';
|
|
2
2
|
const name = process.env.OTEL_SERVICE_NAME || 'mcp-app';
|
|
3
3
|
const logger = logs.getLogger(name);
|
|
4
4
|
// Helper functions to replace console.log
|
package/dist/mcpServer.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import type { ServerCapabilities } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import type { BaseApiFactory, BasePromptFactory, McpFeatureFlags, ResourceFactory } from './types.js';
|
|
4
4
|
export interface AdditionalSetupArgs<Context extends Record<string, unknown>> {
|
|
5
5
|
context: Context;
|
|
6
6
|
server: McpServer;
|
|
@@ -10,8 +10,8 @@ export declare const mcpServerFactory: <Context extends Record<string, unknown>>
|
|
|
10
10
|
name: string;
|
|
11
11
|
version?: string;
|
|
12
12
|
context: Context;
|
|
13
|
-
apiFactories?: readonly
|
|
14
|
-
promptFactories?: readonly
|
|
13
|
+
apiFactories?: readonly BaseApiFactory<Context>[];
|
|
14
|
+
promptFactories?: readonly BasePromptFactory<Context>[];
|
|
15
15
|
resourceFactories?: readonly ResourceFactory<Context>[];
|
|
16
16
|
additionalSetup?: (args: AdditionalSetupArgs<Context>) => void;
|
|
17
17
|
additionalCapabilities?: ServerCapabilities;
|
package/dist/mcpServer.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { McpServer, ResourceTemplate, } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import {
|
|
2
|
+
import { context as otelContext, propagation, SpanKind, SpanStatusCode, trace, } from '@opentelemetry/api';
|
|
3
3
|
import { log } from './logger.js';
|
|
4
4
|
const name = process.env.OTEL_SERVICE_NAME;
|
|
5
5
|
const tracer = trace.getTracer(name ? `${name}.mcpServer` : 'mcpServer');
|
|
@@ -19,7 +19,7 @@ const shouldSkip = (item, enabledSets, disabledSets) => {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
for (const disabledSet of disabledSets) {
|
|
22
|
-
if (disabledSet
|
|
22
|
+
if (disabledSet?.has(item.name)) {
|
|
23
23
|
return true;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -59,7 +59,7 @@ export const mcpServerFactory = ({ name, version = '1.0.0', context, apiFactorie
|
|
|
59
59
|
// make sense.
|
|
60
60
|
title: tool.config.title,
|
|
61
61
|
},
|
|
62
|
-
}, async (args, extra) => {
|
|
62
|
+
}, (async (args, extra) => {
|
|
63
63
|
let traceContext = otelContext.active();
|
|
64
64
|
if (extra?._meta?.traceparent) {
|
|
65
65
|
// Some MCP clients (e.g. pydantic) pass the parent trace context
|
|
@@ -106,7 +106,7 @@ export const mcpServerFactory = ({ name, version = '1.0.0', context, apiFactorie
|
|
|
106
106
|
span.end();
|
|
107
107
|
}
|
|
108
108
|
});
|
|
109
|
-
});
|
|
109
|
+
}));
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
if (enablePrompts) {
|
|
@@ -173,6 +173,9 @@ export const mcpServerFactory = ({ name, version = '1.0.0', context, apiFactorie
|
|
|
173
173
|
list: resource.list &&
|
|
174
174
|
((extra) => tracer.startActiveSpan(`mcp.resource.templated.${resource.name}.list`, async (span) => {
|
|
175
175
|
try {
|
|
176
|
+
if (!resource.list) {
|
|
177
|
+
throw new Error('resource.list is not defined');
|
|
178
|
+
}
|
|
176
179
|
const result = await resource.list(extra);
|
|
177
180
|
span.setAttribute('mcp.resource.list.uris', result.resources.map((r) => r.uri).join(', '));
|
|
178
181
|
span.setStatus({ code: SpanStatusCode.OK });
|
package/dist/stdio.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { type AdditionalSetupArgs } from './mcpServer.js';
|
|
3
|
+
import type { BaseApiFactory, BasePromptFactory, ResourceFactory } from './types.js';
|
|
4
4
|
export declare const stdioServerFactory: <Context extends Record<string, unknown>>({ name, version, context, apiFactories, promptFactories, resourceFactories, additionalSetup, cleanupFn, instructions, }: {
|
|
5
5
|
name: string;
|
|
6
6
|
version?: string;
|
|
7
7
|
context: Context;
|
|
8
|
-
apiFactories?: readonly
|
|
9
|
-
promptFactories?: readonly
|
|
8
|
+
apiFactories?: readonly BaseApiFactory<Context>[];
|
|
9
|
+
promptFactories?: readonly BasePromptFactory<Context>[];
|
|
10
10
|
resourceFactories?: readonly ResourceFactory<Context>[];
|
|
11
11
|
additionalSetup?: (args: AdditionalSetupArgs<Context>) => void;
|
|
12
12
|
cleanupFn?: () => Promise<void>;
|
package/dist/tracing.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type Span, type Tracer } from '@opentelemetry/api';
|
|
2
|
-
import type { GenerateTextResult, ModelMessage } from 'ai';
|
|
2
|
+
import type { GenerateTextResult, ModelMessage, ToolSet } from 'ai';
|
|
3
3
|
export declare const withSpan: <T>(tracer: Tracer, name: string, fn: (span: Span) => Promise<T>) => Promise<T>;
|
|
4
|
-
export declare const addAiResultToSpan: (span: Span, aiResult: GenerateTextResult<
|
|
4
|
+
export declare const addAiResultToSpan: (span: Span, aiResult: GenerateTextResult<ToolSet, unknown>, inputMessages: ModelMessage[]) => void;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,23 +1,47 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
export type ToolConfig<InputArgs extends ZodRawShape, OutputArgs extends ZodRawShape> = {
|
|
1
|
+
import type { CompleteResourceTemplateCallback, ListResourcesCallback, ReadResourceCallback, ReadResourceTemplateCallback, ResourceMetadata } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { GetPromptResult, ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import type { Router } from 'express';
|
|
4
|
+
import type { ZodRawShape, ZodTypeAny, z } from 'zod';
|
|
5
|
+
export type BaseToolConfig = {
|
|
7
6
|
title?: string;
|
|
8
7
|
description?: string;
|
|
9
|
-
inputSchema:
|
|
10
|
-
outputSchema:
|
|
8
|
+
inputSchema: ZodRawShape;
|
|
9
|
+
outputSchema: ZodRawShape;
|
|
11
10
|
annotations?: ToolAnnotations;
|
|
12
11
|
};
|
|
13
|
-
export interface
|
|
12
|
+
export interface BaseApiDefinition {
|
|
14
13
|
name: string;
|
|
15
14
|
method?: 'get' | 'post' | 'put' | 'delete';
|
|
16
15
|
route?: string | string[];
|
|
17
|
-
config:
|
|
16
|
+
config: BaseToolConfig;
|
|
18
17
|
disabled?: boolean;
|
|
19
|
-
fn
|
|
20
|
-
pickResult
|
|
18
|
+
fn(args: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
19
|
+
pickResult?(result: Record<string, unknown>): unknown;
|
|
20
|
+
}
|
|
21
|
+
export type BaseApiFactory<Context extends Record<string, unknown>> = (ctx: Context, featureFlags: McpFeatureFlags) => BaseApiDefinition;
|
|
22
|
+
export type BasePromptConfig = {
|
|
23
|
+
title?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
inputSchema: ZodRawShape;
|
|
26
|
+
};
|
|
27
|
+
export interface BasePromptDefinition {
|
|
28
|
+
name: string;
|
|
29
|
+
config: BasePromptConfig;
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
fn(args: Record<string, unknown>): Promise<GetPromptResult>;
|
|
32
|
+
}
|
|
33
|
+
export type BasePromptFactory<Context extends Record<string, unknown>> = (ctx: Context, featureFlags: McpFeatureFlags) => BasePromptDefinition;
|
|
34
|
+
export type ToolConfig<InputArgs extends ZodRawShape, OutputArgs extends ZodRawShape> = {
|
|
35
|
+
title?: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
inputSchema: InputArgs;
|
|
38
|
+
outputSchema: OutputArgs;
|
|
39
|
+
annotations?: ToolAnnotations;
|
|
40
|
+
};
|
|
41
|
+
export interface ApiDefinition<InputArgs extends ZodRawShape, OutputArgs extends ZodRawShape, SimplifiedOutputArgs = OutputArgs> extends BaseApiDefinition {
|
|
42
|
+
config: ToolConfig<InputArgs, OutputArgs>;
|
|
43
|
+
fn(args: z.objectOutputType<InputArgs, ZodTypeAny>): Promise<z.objectOutputType<OutputArgs, ZodTypeAny>>;
|
|
44
|
+
pickResult?(result: z.objectOutputType<OutputArgs, ZodTypeAny>): SimplifiedOutputArgs;
|
|
21
45
|
}
|
|
22
46
|
export type ApiFactory<Context extends Record<string, unknown>, Input extends ZodRawShape, Output extends ZodRawShape, RestOutput = Output> = (ctx: Context, featureFlags: McpFeatureFlags) => ApiDefinition<Input, Output, RestOutput>;
|
|
23
47
|
export type RouterFactoryResult = [Router, () => void | Promise<void>];
|
|
@@ -26,11 +50,9 @@ export type PromptConfig<InputArgs extends ZodRawShape> = {
|
|
|
26
50
|
description?: string;
|
|
27
51
|
inputSchema: InputArgs;
|
|
28
52
|
};
|
|
29
|
-
export interface PromptDefinition<InputArgs extends ZodRawShape> {
|
|
30
|
-
name: string;
|
|
53
|
+
export interface PromptDefinition<InputArgs extends ZodRawShape> extends BasePromptDefinition {
|
|
31
54
|
config: PromptConfig<InputArgs>;
|
|
32
|
-
|
|
33
|
-
fn: (args: z.objectOutputType<InputArgs, ZodTypeAny>) => Promise<GetPromptResult>;
|
|
55
|
+
fn(args: z.objectOutputType<InputArgs, ZodTypeAny>): Promise<GetPromptResult>;
|
|
34
56
|
}
|
|
35
57
|
export type PromptFactory<Context extends Record<string, unknown>, Input extends ZodRawShape> = (ctx: Context, featureFlags: McpFeatureFlags) => PromptDefinition<Input>;
|
|
36
58
|
export interface TemplatedResourceDefinition {
|
package/dist/types.spec.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tigerdata/mcp-boilerplate",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "MCP boilerplate code for Node.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "TigerData",
|
|
@@ -31,17 +31,15 @@
|
|
|
31
31
|
],
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "tsc",
|
|
34
|
-
"
|
|
34
|
+
"prepublishOnly": "tsc",
|
|
35
35
|
"watch": "tsc --watch",
|
|
36
|
-
"lint": "
|
|
37
|
-
"lint:fix": "eslint --fix",
|
|
38
|
-
"prettier:write": "prettier --write .",
|
|
39
|
-
"prettier:check": "prettier --check ."
|
|
36
|
+
"lint": "./bun x @biomejs/biome check"
|
|
40
37
|
},
|
|
41
38
|
"dependencies": {
|
|
42
|
-
"@
|
|
39
|
+
"@mcp-use/inspector": "^0.13.2",
|
|
40
|
+
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
43
41
|
"@opentelemetry/api": "^1.9.0",
|
|
44
|
-
"@opentelemetry/auto-instrumentations-node": "^0.67.
|
|
42
|
+
"@opentelemetry/auto-instrumentations-node": "^0.67.3",
|
|
45
43
|
"@opentelemetry/exporter-trace-otlp-grpc": "^0.208.0",
|
|
46
44
|
"@opentelemetry/instrumentation-http": "^0.208.0",
|
|
47
45
|
"@opentelemetry/sdk-metrics": "^2.2.0",
|
|
@@ -53,15 +51,14 @@
|
|
|
53
51
|
"zod": "^3.23.8"
|
|
54
52
|
},
|
|
55
53
|
"devDependencies": {
|
|
56
|
-
"@
|
|
57
|
-
"@types/bun": "^1.3.
|
|
54
|
+
"@biomejs/biome": "^2.3.10",
|
|
55
|
+
"@types/bun": "^1.3.5",
|
|
58
56
|
"@types/express": "^5.0.6",
|
|
59
|
-
"@types/node": "^22.19.
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"typescript": "^5.9.3"
|
|
64
|
-
"typescript-eslint": "^8.48.1"
|
|
57
|
+
"@types/node": "^22.19.3",
|
|
58
|
+
"@typescript-eslint/typescript-estree": "^8.50.0",
|
|
59
|
+
"ai": "^5.0.115",
|
|
60
|
+
"eslint": "^9.39.2",
|
|
61
|
+
"typescript": "^5.9.3"
|
|
65
62
|
},
|
|
66
63
|
"publishConfig": {
|
|
67
64
|
"access": "public"
|