@cyanheads/federal-regulations-mcp-server 0.1.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/AGENTS.md +387 -0
- package/CLAUDE.md +387 -0
- package/Dockerfile +127 -0
- package/LICENSE +201 -0
- package/README.md +372 -0
- package/changelog/0.1.x/0.1.0.md +20 -0
- package/changelog/template.md +127 -0
- package/dist/config/server-config.d.ts +32 -0
- package/dist/config/server-config.d.ts.map +1 -0
- package/dist/config/server-config.js +64 -0
- package/dist/config/server-config.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/resources/definitions/cfr-section.resource.d.ts +14 -0
- package/dist/mcp-server/resources/definitions/cfr-section.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/cfr-section.resource.js +77 -0
- package/dist/mcp-server/resources/definitions/cfr-section.resource.js.map +1 -0
- package/dist/mcp-server/resources/definitions/document.resource.d.ts +12 -0
- package/dist/mcp-server/resources/definitions/document.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/document.resource.js +38 -0
- package/dist/mcp-server/resources/definitions/document.resource.js.map +1 -0
- package/dist/mcp-server/resources/definitions/index.d.ts +12 -0
- package/dist/mcp-server/resources/definitions/index.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/index.js +8 -0
- package/dist/mcp-server/resources/definitions/index.js.map +1 -0
- package/dist/mcp-server/tools/definitions/browse-cfr.tool.d.ts +73 -0
- package/dist/mcp-server/tools/definitions/browse-cfr.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/browse-cfr.tool.js +205 -0
- package/dist/mcp-server/tools/definitions/browse-cfr.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/find-comments.tool.d.ts +85 -0
- package/dist/mcp-server/tools/definitions/find-comments.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/find-comments.tool.js +271 -0
- package/dist/mcp-server/tools/definitions/find-comments.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/format-utils.d.ts +7 -0
- package/dist/mcp-server/tools/definitions/format-utils.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/format-utils.js +9 -0
- package/dist/mcp-server/tools/definitions/format-utils.js.map +1 -0
- package/dist/mcp-server/tools/definitions/get-cfr-section.tool.d.ts +50 -0
- package/dist/mcp-server/tools/definitions/get-cfr-section.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/get-cfr-section.tool.js +152 -0
- package/dist/mcp-server/tools/definitions/get-cfr-section.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/get-docket.tool.d.ts +67 -0
- package/dist/mcp-server/tools/definitions/get-docket.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/get-docket.tool.js +154 -0
- package/dist/mcp-server/tools/definitions/get-docket.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/get-document.tool.d.ts +51 -0
- package/dist/mcp-server/tools/definitions/get-document.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/get-document.tool.js +138 -0
- package/dist/mcp-server/tools/definitions/get-document.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/index.d.ts +356 -0
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/index.js +21 -0
- package/dist/mcp-server/tools/definitions/index.js.map +1 -0
- package/dist/mcp-server/tools/definitions/list-open-comments.tool.d.ts +47 -0
- package/dist/mcp-server/tools/definitions/list-open-comments.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/list-open-comments.tool.js +179 -0
- package/dist/mcp-server/tools/definitions/list-open-comments.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/search-rules.tool.d.ts +57 -0
- package/dist/mcp-server/tools/definitions/search-rules.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/search-rules.tool.js +185 -0
- package/dist/mcp-server/tools/definitions/search-rules.tool.js.map +1 -0
- package/dist/services/ecfr/ecfr-service.d.ts +54 -0
- package/dist/services/ecfr/ecfr-service.d.ts.map +1 -0
- package/dist/services/ecfr/ecfr-service.js +303 -0
- package/dist/services/ecfr/ecfr-service.js.map +1 -0
- package/dist/services/ecfr/types.d.ts +105 -0
- package/dist/services/ecfr/types.d.ts.map +1 -0
- package/dist/services/ecfr/types.js +7 -0
- package/dist/services/ecfr/types.js.map +1 -0
- package/dist/services/ecfr/xml.d.ts +15 -0
- package/dist/services/ecfr/xml.d.ts.map +1 -0
- package/dist/services/ecfr/xml.js +103 -0
- package/dist/services/ecfr/xml.js.map +1 -0
- package/dist/services/ecfr-mirror/ecfr-mirror.d.ts +43 -0
- package/dist/services/ecfr-mirror/ecfr-mirror.d.ts.map +1 -0
- package/dist/services/ecfr-mirror/ecfr-mirror.js +267 -0
- package/dist/services/ecfr-mirror/ecfr-mirror.js.map +1 -0
- package/dist/services/federal-register/federal-register-service.d.ts +30 -0
- package/dist/services/federal-register/federal-register-service.d.ts.map +1 -0
- package/dist/services/federal-register/federal-register-service.js +241 -0
- package/dist/services/federal-register/federal-register-service.js.map +1 -0
- package/dist/services/federal-register/types.d.ts +138 -0
- package/dist/services/federal-register/types.d.ts.map +1 -0
- package/dist/services/federal-register/types.js +8 -0
- package/dist/services/federal-register/types.js.map +1 -0
- package/dist/services/regulations-gov/regulations-gov-service.d.ts +55 -0
- package/dist/services/regulations-gov/regulations-gov-service.d.ts.map +1 -0
- package/dist/services/regulations-gov/regulations-gov-service.js +283 -0
- package/dist/services/regulations-gov/regulations-gov-service.js.map +1 -0
- package/dist/services/regulations-gov/types.d.ts +148 -0
- package/dist/services/regulations-gov/types.d.ts.map +1 -0
- package/dist/services/regulations-gov/types.js +7 -0
- package/dist/services/regulations-gov/types.js.map +1 -0
- package/dist/services/request-context.d.ts +13 -0
- package/dist/services/request-context.d.ts.map +1 -0
- package/dist/services/request-context.js +23 -0
- package/dist/services/request-context.js.map +1 -0
- package/package.json +94 -0
- package/scripts/_mirror-context.ts +101 -0
- package/scripts/ecfr-mirror-init.ts +36 -0
- package/scripts/ecfr-mirror-refresh.ts +29 -0
- package/scripts/ecfr-mirror-verify.ts +33 -0
- package/server.json +113 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared bootstrap for the eCFR mirror lifecycle scripts
|
|
3
|
+
* (mirror:init / mirror:refresh / mirror:verify). These run out-of-band (CLI /
|
|
4
|
+
* cron), not inside the MCP request pipeline, so they wire up the minimum the
|
|
5
|
+
* mirror's `sync` ingester needs: the eCFR service (which the ingester calls)
|
|
6
|
+
* and an abort signal. The framework logger is already a global singleton.
|
|
7
|
+
*
|
|
8
|
+
* Imported by the three named lifecycle scripts; travels with them into the npm
|
|
9
|
+
* tarball and the Docker runtime stage (see Dockerfile + package.json files[]).
|
|
10
|
+
*
|
|
11
|
+
* @module scripts/_mirror-context
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { config } from '@cyanheads/mcp-ts-core/config';
|
|
15
|
+
import { StorageService } from '@cyanheads/mcp-ts-core/storage';
|
|
16
|
+
import type { IStorageProvider, ListResult } from '@cyanheads/mcp-ts-core/storage/types';
|
|
17
|
+
import { logger } from '@cyanheads/mcp-ts-core/utils';
|
|
18
|
+
import { initEcfrService } from '@/services/ecfr/ecfr-service.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A minimal Map-backed in-memory storage provider. The mirror owns its own
|
|
22
|
+
* SQLite store and the eCFR service does not use `ctx.state`, so this exists only
|
|
23
|
+
* to satisfy the `initEcfrService(config, storage)` convention; it is never read.
|
|
24
|
+
*/
|
|
25
|
+
class InMemoryProvider implements IStorageProvider {
|
|
26
|
+
private readonly store = new Map<string, unknown>();
|
|
27
|
+
|
|
28
|
+
private k(tenantId: string, key: string): string {
|
|
29
|
+
return `${tenantId}:${key}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async clear(tenantId: string): Promise<number> {
|
|
33
|
+
let n = 0;
|
|
34
|
+
for (const key of this.store.keys()) {
|
|
35
|
+
if (key.startsWith(`${tenantId}:`)) {
|
|
36
|
+
this.store.delete(key);
|
|
37
|
+
n++;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return n;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async delete(tenantId: string, key: string): Promise<boolean> {
|
|
44
|
+
return this.store.delete(this.k(tenantId, key));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async deleteMany(tenantId: string, keys: string[]): Promise<number> {
|
|
48
|
+
let n = 0;
|
|
49
|
+
for (const key of keys) if (this.store.delete(this.k(tenantId, key))) n++;
|
|
50
|
+
return n;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async get<T>(tenantId: string, key: string): Promise<T | null> {
|
|
54
|
+
return (this.store.get(this.k(tenantId, key)) as T) ?? null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async getMany<T>(tenantId: string, keys: string[]): Promise<Map<string, T>> {
|
|
58
|
+
const out = new Map<string, T>();
|
|
59
|
+
for (const key of keys) {
|
|
60
|
+
const v = this.store.get(this.k(tenantId, key));
|
|
61
|
+
if (v !== undefined) out.set(key, v as T);
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async list(tenantId: string, prefix: string): Promise<ListResult> {
|
|
67
|
+
const full = `${tenantId}:${prefix}`;
|
|
68
|
+
const keys = [...this.store.keys()]
|
|
69
|
+
.filter((k) => k.startsWith(full))
|
|
70
|
+
.map((k) => k.slice(tenantId.length + 1));
|
|
71
|
+
return { keys };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async set(tenantId: string, key: string, value: unknown): Promise<void> {
|
|
75
|
+
this.store.set(this.k(tenantId, key), value);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async setMany(tenantId: string, entries: Map<string, unknown>): Promise<void> {
|
|
79
|
+
for (const [key, value] of entries) this.store.set(this.k(tenantId, key), value);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Initialize the services the mirror sync depends on. The mirror reads
|
|
85
|
+
* `getEcfrService()` from inside its `sync` generator, so it must be constructed
|
|
86
|
+
* before any `runSync` call.
|
|
87
|
+
*/
|
|
88
|
+
export async function bootstrapMirrorServices(): Promise<void> {
|
|
89
|
+
await logger.initialize('info');
|
|
90
|
+
const storage = new StorageService(new InMemoryProvider());
|
|
91
|
+
initEcfrService(config, storage);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** An abort signal that fires on SIGINT/SIGTERM so a long init stops cleanly. */
|
|
95
|
+
export function signalFromProcess(): AbortSignal {
|
|
96
|
+
const controller = new AbortController();
|
|
97
|
+
const stop = () => controller.abort();
|
|
98
|
+
process.once('SIGINT', stop);
|
|
99
|
+
process.once('SIGTERM', stop);
|
|
100
|
+
return controller.signal;
|
|
101
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview `mirror:init` — full out-of-band ingest of the codified CFR into
|
|
4
|
+
* the local SQLite + FTS5 mirror. Idempotent and resumable: re-running after an
|
|
5
|
+
* interrupt continues from the persisted cursor/checkpoint. A full sweep of all
|
|
6
|
+
* ~50 titles can take a long time and must never run on server startup.
|
|
7
|
+
*
|
|
8
|
+
* @module scripts/ecfr-mirror-init
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { logger } from '@cyanheads/mcp-ts-core/utils';
|
|
12
|
+
import { ecfrMirror } from '@/services/ecfr-mirror/ecfr-mirror.js';
|
|
13
|
+
import { bootstrapMirrorServices, signalFromProcess } from './_mirror-context.js';
|
|
14
|
+
|
|
15
|
+
await bootstrapMirrorServices();
|
|
16
|
+
|
|
17
|
+
logger.info('eCFR mirror init: starting full sync');
|
|
18
|
+
const result = await ecfrMirror.runSync({
|
|
19
|
+
mode: 'init',
|
|
20
|
+
signal: signalFromProcess(),
|
|
21
|
+
onProgress: (info) => {
|
|
22
|
+
logger.info('eCFR mirror init progress', {
|
|
23
|
+
pages: info.pages,
|
|
24
|
+
records: info.records,
|
|
25
|
+
checkpoint: info.checkpoint,
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
logger.info('eCFR mirror init: complete', {
|
|
31
|
+
pagesFetched: result.pagesFetched,
|
|
32
|
+
recordsApplied: result.recordsApplied,
|
|
33
|
+
total: result.total,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
await ecfrMirror.close();
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview `mirror:refresh` — incremental refresh of the codified CFR mirror
|
|
4
|
+
* from the persisted high-water checkpoint. Re-walks the titles and upserts
|
|
5
|
+
* current text; the dataset stays queryable throughout. Wired on a weekly cron in
|
|
6
|
+
* the server's `setup()`, and runnable on demand here.
|
|
7
|
+
*
|
|
8
|
+
* @module scripts/ecfr-mirror-refresh
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { logger } from '@cyanheads/mcp-ts-core/utils';
|
|
12
|
+
import { ecfrMirror } from '@/services/ecfr-mirror/ecfr-mirror.js';
|
|
13
|
+
import { bootstrapMirrorServices, signalFromProcess } from './_mirror-context.js';
|
|
14
|
+
|
|
15
|
+
await bootstrapMirrorServices();
|
|
16
|
+
|
|
17
|
+
logger.info('eCFR mirror refresh: starting');
|
|
18
|
+
const result = await ecfrMirror.runSync({
|
|
19
|
+
mode: 'refresh',
|
|
20
|
+
signal: signalFromProcess(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
logger.info('eCFR mirror refresh: complete', {
|
|
24
|
+
pagesFetched: result.pagesFetched,
|
|
25
|
+
recordsApplied: result.recordsApplied,
|
|
26
|
+
total: result.total,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
await ecfrMirror.close();
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview `mirror:verify` — read-only health check of the codified CFR
|
|
4
|
+
* mirror: prints sync status (ready marker, checkpoint, record count) and runs a
|
|
5
|
+
* sample FTS query so an operator can confirm the index is queryable.
|
|
6
|
+
*
|
|
7
|
+
* @module scripts/ecfr-mirror-verify
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { logger } from '@cyanheads/mcp-ts-core/utils';
|
|
11
|
+
import { ecfrMirror, mirrorSearch } from '@/services/ecfr-mirror/ecfr-mirror.js';
|
|
12
|
+
import { bootstrapMirrorServices } from './_mirror-context.js';
|
|
13
|
+
|
|
14
|
+
await bootstrapMirrorServices();
|
|
15
|
+
|
|
16
|
+
const status = await ecfrMirror.status();
|
|
17
|
+
logger.info('eCFR mirror status', {
|
|
18
|
+
ready: status.ready,
|
|
19
|
+
status: status.status,
|
|
20
|
+
total: status.total,
|
|
21
|
+
checkpoint: status.checkpoint,
|
|
22
|
+
completedAt: status.completedAt,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (status.ready) {
|
|
26
|
+
const sample = await mirrorSearch('definitions', undefined, 3);
|
|
27
|
+
logger.info('eCFR mirror sample query "definitions"', {
|
|
28
|
+
totalCount: sample.totalCount,
|
|
29
|
+
firstHit: sample.results[0]?.cfrCite ?? '(none)',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
await ecfrMirror.close();
|
package/server.json
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.cyanheads/federal-regulations-mcp-server",
|
|
4
|
+
"description": "Search and trace US federal rules across the Federal Register, eCFR, and Regulations.gov.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"url": "https://github.com/cyanheads/federal-regulations-mcp-server",
|
|
7
|
+
"source": "github"
|
|
8
|
+
},
|
|
9
|
+
"version": "0.1.0",
|
|
10
|
+
"packages": [
|
|
11
|
+
{
|
|
12
|
+
"registryType": "npm",
|
|
13
|
+
"registryBaseUrl": "https://registry.npmjs.org",
|
|
14
|
+
"identifier": "@cyanheads/federal-regulations-mcp-server",
|
|
15
|
+
"runtimeHint": "node",
|
|
16
|
+
"version": "0.1.0",
|
|
17
|
+
"packageArguments": [
|
|
18
|
+
{
|
|
19
|
+
"type": "positional",
|
|
20
|
+
"value": "run"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"type": "positional",
|
|
24
|
+
"value": "start:stdio"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"environmentVariables": [
|
|
28
|
+
{
|
|
29
|
+
"name": "REGULATIONS_GOV_API_KEY",
|
|
30
|
+
"description": "api.data.gov key for the Regulations.gov tools (get_docket, find_comments). Free at https://api.data.gov/signup/. The Federal Register and eCFR tools work without it.",
|
|
31
|
+
"format": "string",
|
|
32
|
+
"isRequired": false,
|
|
33
|
+
"isSecret": true
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "MCP_LOG_LEVEL",
|
|
37
|
+
"description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn').",
|
|
38
|
+
"format": "string",
|
|
39
|
+
"isRequired": false,
|
|
40
|
+
"default": "info"
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"transport": {
|
|
44
|
+
"type": "stdio"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"registryType": "npm",
|
|
49
|
+
"registryBaseUrl": "https://registry.npmjs.org",
|
|
50
|
+
"identifier": "@cyanheads/federal-regulations-mcp-server",
|
|
51
|
+
"runtimeHint": "node",
|
|
52
|
+
"version": "0.1.0",
|
|
53
|
+
"packageArguments": [
|
|
54
|
+
{
|
|
55
|
+
"type": "positional",
|
|
56
|
+
"value": "run"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"type": "positional",
|
|
60
|
+
"value": "start:http"
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"environmentVariables": [
|
|
64
|
+
{
|
|
65
|
+
"name": "MCP_HTTP_HOST",
|
|
66
|
+
"description": "The hostname for the HTTP server.",
|
|
67
|
+
"format": "string",
|
|
68
|
+
"isRequired": false,
|
|
69
|
+
"default": "127.0.0.1"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "MCP_HTTP_PORT",
|
|
73
|
+
"description": "The port to run the HTTP server on.",
|
|
74
|
+
"format": "string",
|
|
75
|
+
"isRequired": false,
|
|
76
|
+
"default": "3010"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "MCP_HTTP_ENDPOINT_PATH",
|
|
80
|
+
"description": "The endpoint path for the MCP server.",
|
|
81
|
+
"format": "string",
|
|
82
|
+
"isRequired": false,
|
|
83
|
+
"default": "/mcp"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"name": "MCP_AUTH_MODE",
|
|
87
|
+
"description": "Authentication mode to use: 'none', 'jwt', or 'oauth'.",
|
|
88
|
+
"format": "string",
|
|
89
|
+
"isRequired": false,
|
|
90
|
+
"default": "none"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "REGULATIONS_GOV_API_KEY",
|
|
94
|
+
"description": "api.data.gov key for the Regulations.gov tools (get_docket, find_comments). Free at https://api.data.gov/signup/. The Federal Register and eCFR tools work without it.",
|
|
95
|
+
"format": "string",
|
|
96
|
+
"isRequired": false,
|
|
97
|
+
"isSecret": true
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "MCP_LOG_LEVEL",
|
|
101
|
+
"description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn').",
|
|
102
|
+
"format": "string",
|
|
103
|
+
"isRequired": false,
|
|
104
|
+
"default": "info"
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"transport": {
|
|
108
|
+
"type": "streamable-http",
|
|
109
|
+
"url": "http://localhost:3010/mcp"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
}
|