somamcp 1.4.1 → 1.5.1

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
@@ -400,6 +400,39 @@ The ⚠️ rows are limits of `EdgeFastMCP`, which exposes no removal API, has n
400
400
 
401
401
  Bun deliberately reports `"node"`: it is a Node-family server runtime with full Node APIs, so that is the accurate answer even though `somamcp/edge` runs there.
402
402
 
403
+ ## MCP SDK 2.x Backend (opt-in)
404
+
405
+ `createSdkBackend` builds on the official MCP TypeScript SDK 2.x (`@modelcontextprotocol/server`). One endpoint serves both protocol revisions:
406
+
407
+ - **`2026-07-28`**, which current Claude clients request first. The default FastMCP 4.x backend answers that request with HTTP 400, and a client that doesn't retry with the older handshake ends up with no tools.
408
+ - **2025-era clients**, which open with `initialize`.
409
+
410
+ Pass it as `backend`. Nothing else changes:
411
+
412
+ ```typescript
413
+ import { createServer } from "somamcp"
414
+ import { createSdkBackend } from "somamcp/backend"
415
+
416
+ const server = createServer({ name: "my-server", version: "1.0.0", backend: createSdkBackend })
417
+
418
+ await server.start({ transportType: "httpStream", httpStream: { port: 3000 } })
419
+ // or: await server.start({ transportType: "stdio" })
420
+ ```
421
+
422
+ How it differs from the FastMCP backend:
423
+
424
+ - **Stateless only.** Every request gets a fresh SDK server built from somamcp's registry. There are no sessions, `connect`/`disconnect` events never fire, and a 2025 client's `GET` or `DELETE` is answered `405`. `httpStream.stateless: false` and `eventStore` are ignored, with a warning through `logger`.
425
+ - **`authenticate` receives a web `Request`**, not Node's `http.IncomingMessage`. Read headers with `getRequestHeader` and the same function works on both backends. Rejecting with a `Response` serves that response as-is. Any other rejection, a synchronous throw, or a nullish result (as on FastMCP) is a `401`. `canAccess` is only ever called with a real session: with none, gated tools are hidden when `authenticate` is configured and shown otherwise, as on FastMCP.
426
+ - **Errors follow SDK 2.x and the current spec.** Calling an unknown tool, or one hidden by `canAccess`, is a JSON-RPC `InvalidParams` error, as on FastMCP. Invalid arguments are an `isError` tool result, so the model can read the message and retry. FastMCP reports them as an `InvalidParams` protocol error.
427
+ - **Schemas must describe themselves as JSON Schema** (`~standard.jsonSchema`): zod 4, ArkType, or Valibot via `@valibot/to-json-schema`. Other schemas still validate, but clients see an empty argument list; `addTool` warns through `logger`.
428
+ - **`context.client.version`** is filled in for `2026-07-28` clients, which send their client info on every request. It is `undefined` for 2025 clients, which send it only during `initialize`.
429
+ - **`httpStream.host` defaults to `localhost`**, as on FastMCP. Pass `host: "0.0.0.0"` to listen on every interface.
430
+ - **`streamKeepalive`** maps to the SDK's SSE comment frames (`enabled` and `intervalMs`; the default is 20 s, as on FastMCP). FastMCP sends log notifications instead. With it on, every tool call is answered as an SSE stream, so a long call that produces no output still gets keepalives. `enableJsonResponse` turns them off; it applies to `2026-07-28` exchanges only, so a 2025 client's responses are unchanged by it.
431
+ - **`context.log` follows the client's log level.** A `2026-07-28` client receives tool logs only when its request asks for a log level (`io.modelcontextprotocol/logLevel`); otherwise the SDK drops them. 2025 clients receive them as before. Progress (`reportProgress`) is unaffected.
432
+ - **Health reports `running` from construction**, because the backend can answer `fetch()` before `start()`. FastMCP reports `stopped` until `start()`. Both report `stopped` after `stop()`.
433
+ - **Removal is real:** `removeTool`, `removeResource` and `removePrompt` apply from the next request.
434
+ - **`backendOptions`** takes `mcpPath` (the endpoint for `fetch()` use; `httpStream.endpoint` overrides it) and `stdioTransport` (a transport to use in place of the process's stdin/stdout). FastMCP's `ping`, `health`, `roots` and `oauth` options don't apply.
435
+
403
436
  ## Backend Abstraction
404
437
 
405
438
  The underlying MCP framework is accessed exclusively through the `BackendAdapter` interface. `createServer` accepts a `backend` factory — this is how `somamcp/edge` swaps in the edge adapter:
@@ -501,8 +534,8 @@ createServer({
501
534
 
502
535
  **Backend** (via `somamcp/backend`)
503
536
 
504
- - `createFastMCPBackend`
505
- - Types: `BackendAdapter`, `BackendFactory`, `BackendSession`
537
+ - `createFastMCPBackend`, `createSdkBackend`
538
+ - Types: `BackendAdapter`, `BackendFactory`, `BackendSession`, `SdkBackendOptions`
506
539
 
507
540
  ## Scripts
508
541
 
@@ -1,2 +1,2 @@
1
- import { a as BackendSession, i as BackendFactory, n as BackendAdapter, r as BackendEvents, t as createFastMCPBackend } from "../index-CSy9en2A.js";
2
- export { type BackendAdapter, type BackendEvents, type BackendFactory, type BackendSession, createFastMCPBackend };
1
+ import { a as BackendEvents, i as BackendAdapter, n as createSdkBackend, o as BackendFactory, r as createFastMCPBackend, s as BackendSession, t as SdkBackendOptions } from "../index-C2wa9nmp.js";
2
+ export { type BackendAdapter, type BackendEvents, type BackendFactory, type BackendSession, type SdkBackendOptions, createFastMCPBackend, createSdkBackend };
@@ -1 +1 @@
1
- import{t as e}from"../backend-Dd0n_9Ai.js";export{e as createFastMCPBackend};
1
+ export{n as createFastMCPBackend,t as createSdkBackend}from"../backend-D0qSyfXw.js";
@@ -0,0 +1 @@
1
+ import{FastMCP as e,ServerState as t}from"fastmcp";import{ProtocolError as n,ProtocolErrorCode as r,ResourceNotFoundError as i,Server as a,UriTemplate as o,createMcpHandler as s}from"@modelcontextprotocol/server";import{List as c,Map as l,Option as u,Ref as d,Try as f,Tuple as p}from"functype";import{Hono as m}from"hono";import{cors as h}from"hono/cors";const g=e=>{switch(e){case t.Running:return`running`;case t.Error:return`error`;default:return`stopped`}},_=(t,n)=>{let r={...n,authenticate:t.authenticate,instructions:t.instructions,logger:t.logger,name:t.name,...t.streamKeepalive?{streamKeepalive:t.streamKeepalive}:{},version:t.version},i=new e(r);return{get serverState(){return g(i.serverState)},get sessions(){return i.sessions.map(e=>({sessionId:e.sessionId}))},addPrompt:e=>{i.addPrompt(e)},addResource:e=>{i.addResource(e)},addResourceTemplate:(...e)=>{i.addResourceTemplate(...e)},addTool:e=>{i.addTool(e)},fetch:async e=>i.getApp().fetch(e),getApp:()=>i.getApp(),on:(e,t)=>{i.on(e,t)},removePrompt:e=>i.removePrompt(e),removeResource:e=>i.removeResource(e),removeTool:e=>i.removeTool(e),start:async e=>{e?e.transportType===`httpStream`?await i.start({httpStream:e.httpStream,transportType:`httpStream`}):await i.start({transportType:`stdio`}):await i.start()},stop:()=>i.stop()}},v={properties:{},type:`object`},y=e=>u(e[`~standard`].jsonSchema).isSome(),b=e=>e.flatMap(e=>u(e[`~standard`].jsonSchema)).map(e=>e.input({target:`draft-2020-12`})).orElse(v),x=e=>typeof e==`string`?{content:[{text:e,type:`text`}]}:e===void 0?{content:[]}:`content`in e?e:{content:[e]},S=e=>({content:[{text:e,type:`text`}],isError:!0}),C=(e,t)=>({contents:(Array.isArray(e)?e:[e]).map(e=>({mimeType:e.mimeType??t.mimeType,uri:e.uri??t.uri,...`blob`in e?{blob:e.blob}:{text:e.text}}))}),w=e=>typeof e==`string`?{messages:[{content:{text:e,type:`text`},role:`user`}]}:e,T={values:[]},E=e=>({completion:e.orElse(T)}),D=(e,t)=>{let n=e.filter(e=>e.startsWith(t));return{total:n.length,values:n}},O=(e,t,n)=>{let r=t=>e.mcpReq.notify(t).catch(()=>{}),i=t=>(n,r)=>{e.mcpReq.log(t,r===void 0?n:{data:r,message:n}).catch(()=>{})},a=u(e.mcpReq._meta?.progressToken);return{client:{version:u(e.mcpReq.envelope?.[`io.modelcontextprotocol/clientInfo`]).map(e=>e.version).orUndefined()},log:{debug:i(`debug`),error:i(`error`),info:i(`info`),warn:i(`warning`)},reportProgress:async({progress:e,total:t})=>{await a.fold(async()=>{},n=>r({method:`notifications/progress`,params:{progress:e,progressToken:n,total:t}}))},requestId:String(e.mcpReq.id),session:t.orUndefined(),sessionId:e.sessionId,streamContent:async e=>{await r({method:`notifications/tool/streamContent`,params:{content:Array.isArray(e)?e:[e],toolName:n}})}}},k=e=>c([...e].map(([,e])=>e)),A=(...e)=>e.reduce((e,t)=>e.fold(()=>t(),()=>e),u.none()),j=e=>e instanceof Error?e.message:String(e),M=e=>`Tool '${e.name}' timed out after ${e.timeoutMs}ms. Consider increasing timeoutMs or optimizing the tool implementation.`,N=(e,t)=>u(e.timeoutMs).fold(()=>t,n=>{let r=d(u.none()),i=new Promise((t,i)=>{r.set(u(setTimeout(()=>i(Error(M(e))),n)))});return Promise.race([t,i]).finally(()=>r.get().forEach(clearTimeout))}),P=(e,t)=>u(e.parameters).fold(()=>Promise.resolve({value:t}),e=>Promise.resolve(e[`~standard`].validate(t))),F=e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Array.isArray(t)?t.join(`,`):t])),I=(e,t,s)=>{let l=s.orUndefined(),d=e=>s.fold(()=>!(t.authRequired&&e.canAccess),t=>!e.canAccess||e.canAccess(t)),p=t=>e.tools().get(t).filter(d),m=new a({name:t.name,version:t.version},{capabilities:{completions:{},logging:{},prompts:{},resources:{},tools:{}},instructions:t.instructions});m.setRequestHandler(`tools/list`,()=>({tools:k(e.tools()).filter(d).map(e=>({...e._meta?{_meta:e._meta}:{},...e.annotations?{annotations:e.annotations}:{},description:e.description,inputSchema:b(u(e.parameters)),name:e.name,...e.outputSchema?{outputSchema:b(u(e.outputSchema))}:{},...e.annotations?.title?{title:e.annotations.title}:{}})).toArray()}));let h=async(e,t,n)=>{let r=await P(e,t);return`issues`in r?S(`Invalid arguments for tool '${e.name}': ${r.issues.map(e=>e.message).join(`; `)}`):(await f.fromPromise(N(e,e.execute(r.value,n)))).fold(e=>S(j(e)),e=>x(e))},g=e=>p(e).orThrow(()=>new n(r.InvalidParams,`Unknown tool: ${e}`));m.setRequestHandler(`tools/call`,(e,t)=>{let{arguments:n,name:r}=e.params;return h(g(r),n??{},O(t,s,r))}),m.setRequestHandler(`resources/list`,()=>({resources:k(e.resources()).map(e=>({description:e.description,mimeType:e.mimeType,name:e.name,uri:e.uri})).toArray()})),m.setRequestHandler(`resources/templates/list`,()=>({resourceTemplates:k(e.templates()).map(e=>({description:e.description,mimeType:e.mimeType,name:e.name,uriTemplate:e.uriTemplate})).toArray()}));let _=t=>A(()=>k(e.resources()).find(e=>e.uri===t).map(e=>({load:()=>e.load(l),mimeType:e.mimeType})),()=>k(e.templates()).map(e=>({template:e,variables:u(new o(e.uriTemplate).match(t))})).find(e=>e.variables.isSome()).map(({template:e,variables:t})=>({load:()=>e.load(F(t.orElse({})),l),mimeType:e.mimeType}))),v=async e=>{let t=_(e).orThrow(()=>new i(e));return C(await t.load(),{mimeType:t.mimeType,uri:e})};m.setRequestHandler(`resources/read`,e=>v(e.params.uri)),m.setRequestHandler(`prompts/list`,()=>({prompts:k(e.prompts()).map(e=>({arguments:e.arguments?.map(e=>({description:e.description,name:e.name,required:e.required})),description:e.description,name:e.name})).toArray()}));let y=async(t,i)=>{let a=e.prompts().get(t).orThrow(()=>new n(r.InvalidParams,`Unknown prompt: ${t}`)),o=c(a.arguments??[]).filter(e=>e.required===!0&&!(e.name in i));if(!o.isEmpty){let e=o.map(e=>e.name).toArray().join(`, `);throw new n(r.InvalidParams,`Prompt '${t}' is missing required arguments: ${e}`)}return w(await a.load(i,l))};m.setRequestHandler(`prompts/get`,e=>y(e.params.name,e.params.arguments??{}));let T=(t,n,r)=>{let i=e.prompts().get(t),a=i.flatMap(e=>c(e.arguments??[]).find(e=>e.name===n));return A(()=>a.flatMap(e=>u(e.complete)).map(e=>()=>e(r,l)),()=>a.flatMap(e=>u(e.enum)).map(e=>()=>Promise.resolve(D(e,r))),()=>i.flatMap(e=>u(e.complete)).map(e=>()=>e(n,r,l)))},M=(t,n,r)=>{let i=k(e.templates()).find(e=>e.uriTemplate===t),a=i.flatMap(e=>c(e.arguments).find(e=>e.name===n));return A(()=>a.flatMap(e=>u(e.complete)).map(e=>()=>e(r,l)),()=>i.flatMap(e=>u(e.complete)).map(e=>()=>e(n,r,l)))};return m.setRequestHandler(`completion/complete`,async e=>{let{argument:t,ref:n}=e.params,r=n.type===`ref/prompt`?T(n.name,t.name,t.value):M(n.uri,t.name,t.value);return E(await r.foldAsync(()=>Promise.resolve(u.none()),async e=>u(await e())))}),m},L=`somamcp/session`,R=(e,t)=>{let n=u(e.logger),r=e=>n.forEach(t=>t.warn(`[somamcp/sdk] ${e}`)),i=d(l.empty()),a=d(l.empty()),o=d(l.empty()),c=d(l.empty()),g={prompts:()=>c.get(),resources:()=>a.get(),templates:()=>o.get(),tools:()=>i.get()},_=(e,t,n)=>{e.set(e.get().add(p([t,n])))},v=(e,t)=>{e.set(e.get().remove(t))},b={authRequired:e.authenticate!==void 0,instructions:e.instructions,name:e.name,version:e.version},x=u(e.streamKeepalive).filter(e=>e.enabled===!0).map(e=>e.intervalMs??2e4),S=x.fold(()=>`auto`,()=>`sse`),C=e=>s(({authInfo:e})=>I(g,b,u(e).flatMap(e=>u(e.extra?.[L]))),{keepAliveMs:x.orUndefined(),onerror:e=>n.forEach(t=>t.error(`[somamcp/sdk]`,e)),responseMode:e}),w=d(S),T=d(C(w.get())),E=d(u(t).flatMap(e=>u(e.mcpPath)).orElse(`/mcp`)),D=d(u.none()),O=d(u.none()),k=d(`running`),A=(e,t)=>t instanceof Response?t:e.json({error:`Unauthorized`},401),j=(e,t)=>Promise.resolve().then(()=>e(t)).then(e=>u(e).fold(()=>Promise.reject(/* @__PURE__ */ Error(`Authentication required`)),e=>Promise.resolve(e))),M=async t=>{let n=t.req.raw;return e.authenticate?j(e.authenticate,n).then(e=>T.get().fetch(n,{authInfo:{clientId:``,extra:{[L]:e},scopes:[],token:``}}),e=>A(t,e)):T.get().fetch(n)},N=new m;N.use(`*`,async(e,t)=>e.req.path===E.get()?D.get().fold(()=>M(e),async t=>await t(e,async()=>{e.res=await M(e)})??e.res):t());let P=e=>{u(e.endpoint).forEach(e=>E.set(e)),u(e.cors).filter(e=>e!==!1).forEach(e=>D.set(u(h(e===!0?{}:e)))),e.enableJsonResponse===!0&&(x.isSome()&&r(`enableJsonResponse disables streamKeepalive: JSON responses cannot carry keepalive frames.`),w.set(`json`),T.set(C(`json`))),e.stateless===!1&&r(`stateful sessions are not supported by the SDK backend; serving statelessly.`),e.eventStore!==void 0&&r(`eventStore is not supported by the SDK backend; ignoring.`)},F=async()=>{let{listenStdio:r}=await import(`./listen-ZkXBwyaw.js`),i=e.authenticate?(await f.fromPromise(j(e.authenticate,void 0))).fold(e=>(n.forEach(t=>t.error(`[somamcp/sdk] authentication failed for stdio transport:`,e.message)),u.none()),e=>u(e)):u.none();return r(()=>I(g,b,i),u(t).flatMap(e=>u(e.stdioTransport)).orUndefined())},R=async e=>{let{listenHttp:t}=await import(`./listen-ZkXBwyaw.js`);return P(e),t(N,e)};return{get serverState(){return k.get()},get sessions(){return[]},addPrompt:e=>{_(c,e.name,e)},addResource:e=>{_(a,e.name,e)},addResourceTemplate:(...e)=>{let t=e[0];_(o,t.name,t)},addTool:e=>{e.parameters&&!y(e.parameters)&&r(`tool "${e.name}": its schema has no ~standard.jsonSchema, so clients see an empty argument list. Use zod 4, ArkType, or Valibot with @valibot/to-json-schema.`),_(i,e.name,e)},fetch:async e=>N.fetch(e),getApp:()=>N,on:()=>{},removePrompt:e=>{v(c,e)},removeResource:e=>{v(a,e)},removeTool:e=>{v(i,e)},start:async e=>{if(O.get().isSome()){r(`start() called while already listening; ignoring. Call stop() first to restart.`);return}let t=await f.fromPromise(e?.transportType===`httpStream`?R(e.httpStream):F());t.isFailure()&&k.set(`error`),O.set(u(t.orThrow())),k.set(`running`)},stop:async()=>{await T.get().close(),await O.get().fold(async()=>{},e=>e.close()),O.set(u.none()),T.set(C(w.get())),k.set(`stopped`)}}};export{_ as n,R as t};
package/dist/edge.d.ts CHANGED
@@ -156,6 +156,25 @@ type Resource<T extends SessionAuth = SessionAuth> = {
156
156
  name: string;
157
157
  uri: string;
158
158
  };
159
+ type ResourceTemplateArgument<T extends SessionAuth = SessionAuth> = Readonly<{
160
+ complete?: (value: string, auth?: T) => Promise<Completion>;
161
+ description?: string;
162
+ name: string;
163
+ required?: boolean;
164
+ }>;
165
+ /**
166
+ * A family of resources addressed by an RFC 6570 URI template, e.g. `docs://{path}`.
167
+ * `load` receives the variables matched from the requested URI.
168
+ */
169
+ type ResourceTemplate<T extends SessionAuth = SessionAuth> = {
170
+ arguments: ResourceTemplateArgument<T>[];
171
+ complete?: (name: string, value: string, auth?: T) => Promise<Completion>;
172
+ description?: string;
173
+ load: (args: Record<string, string>, auth?: T) => Promise<ResourceResult | ResourceResult[]>;
174
+ mimeType?: string;
175
+ name: string;
176
+ uriTemplate: string;
177
+ };
159
178
  type PromptArgument<T extends SessionAuth = SessionAuth> = Readonly<{
160
179
  complete?: (value: string, auth?: T) => Promise<Completion>;
161
180
  description?: string;
@@ -174,7 +193,7 @@ type Prompt<T extends SessionAuth = SessionAuth, Args extends PromptArgument<T>[
174
193
  name: string;
175
194
  };
176
195
  type ServerStatus = "error" | "running" | "stopped";
177
- declare class UserError extends Error {
196
+ export declare class UserError extends Error {
178
197
  constructor(message: string);
179
198
  }
180
199
  //#endregion
@@ -315,9 +334,9 @@ type RuntimeInfo = {
315
334
  /** Which runtime family reported the fields above. Absent on pre-1.2 builds. */
316
335
  runtime?: "edge" | "node";
317
336
  };
318
- declare const readBuildInfoFromEnv: () => BuildInfo;
319
- declare const resolveBuildInfo: (override?: BuildInfo) => BuildInfo;
320
- declare const getRuntimeInfo: () => RuntimeInfo;
337
+ export declare const readBuildInfoFromEnv: () => BuildInfo;
338
+ export declare const resolveBuildInfo: (override?: BuildInfo) => BuildInfo;
339
+ export declare const getRuntimeInfo: () => RuntimeInfo;
321
340
  //#endregion
322
341
  //#region src/gateway/types.d.ts
323
342
  type GatewayConfig = {
@@ -402,7 +421,7 @@ type AuthMiddlewareConfig = {
402
421
  authenticate?: Authenticate;
403
422
  onUnauthorized?: OnUnauthorized;
404
423
  };
405
- declare const createAuthMiddleware: ({ authenticate, onUnauthorized }: AuthMiddlewareConfig) => MiddlewareHandler;
424
+ export declare const createAuthMiddleware: ({ authenticate, onUnauthorized }: AuthMiddlewareConfig) => MiddlewareHandler;
406
425
  //#endregion
407
426
  //#region src/auth/request.d.ts
408
427
  /**
@@ -417,7 +436,7 @@ declare const createAuthMiddleware: ({ authenticate, onUnauthorized }: AuthMiddl
417
436
  * absent or the request shape is not recognized — matches the `Headers.get`
418
437
  * shape callers already write against.
419
438
  */
420
- declare const getRequestHeader: (request: unknown, name: string) => string | undefined;
439
+ export declare const getRequestHeader: (request: unknown, name: string) => string | undefined;
421
440
  //#endregion
422
441
  //#region src/types/routes.d.ts
423
442
  type RouteMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
@@ -546,7 +565,7 @@ type SomaServerInstance<T extends SessionAuth = SessionAuth> = {
546
565
  * module — including `somamcp/edge`. The entry barrels supply the default instead:
547
566
  * `somamcp` binds createFastMCPBackend, `somamcp/edge` binds createEdgeBackend.
548
567
  */
549
- declare const createServerCore: <T extends SessionAuth = SessionAuth>(options: SomaServerOptions<T> & {
568
+ export declare const createServerCore: <T extends SessionAuth = SessionAuth>(options: SomaServerOptions<T> & {
550
569
  backend: BackendFactory<T>;
551
570
  }) => SomaServerInstance<T>;
552
571
  //#endregion
@@ -564,13 +583,13 @@ type EdgeBackendOptions = {
564
583
  * registers its own `/health` at construction, and Hono is first-match-wins, so
565
584
  * mounting it first would shadow somamcp's health artifact.
566
585
  */
567
- declare const createEdgeBackend: <T extends SessionAuth = SessionAuth>(config: ServerConfig<T>, backendOptions?: Record<string, unknown>) => BackendAdapter<T>;
586
+ export declare const createEdgeBackend: <T extends SessionAuth = SessionAuth>(config: ServerConfig<T>, backendOptions?: Record<string, unknown>) => BackendAdapter<T>;
568
587
  //#endregion
569
588
  //#region src/telemetry/CompositeTelemetry.d.ts
570
- declare const createCompositeTelemetry: (collectors: ReadonlyArray<TelemetryCollector>) => TelemetryCollector;
589
+ export declare const createCompositeTelemetry: (collectors: ReadonlyArray<TelemetryCollector>) => TelemetryCollector;
571
590
  //#endregion
572
591
  //#region src/telemetry/ConsoleTelemetry.d.ts
573
- declare const createConsoleTelemetry: (prefix?: string) => TelemetryCollector;
592
+ export declare const createConsoleTelemetry: (prefix?: string) => TelemetryCollector;
574
593
  //#endregion
575
594
  //#region src/telemetry/EnrichedError.d.ts
576
595
  type EnrichedErrorResponse = {
@@ -579,14 +598,14 @@ type EnrichedErrorResponse = {
579
598
  relatedState?: Record<string, unknown>;
580
599
  suggestions?: ReadonlyArray<string>;
581
600
  };
582
- declare const classifyError: (error: unknown) => ErrorCategory;
583
- declare const createEnrichedError: (error: unknown, context?: {
601
+ export declare const classifyError: (error: unknown) => ErrorCategory;
602
+ export declare const createEnrichedError: (error: unknown, context?: {
584
603
  gatewayStatus?: string;
585
604
  toolName?: string;
586
605
  }) => EnrichedErrorResponse;
587
606
  //#endregion
588
607
  //#region src/telemetry/NoopTelemetry.d.ts
589
- declare const NoopTelemetry: TelemetryCollector;
608
+ export declare const NoopTelemetry: TelemetryCollector;
590
609
  //#endregion
591
610
  //#region src/telemetry/telemetryWrapper.d.ts
592
611
  /**
@@ -602,37 +621,37 @@ declare const NoopTelemetry: TelemetryCollector;
602
621
  * The failure path converts an error to a `ContentResult` with `isError: true`
603
622
  * and the enriched error payload as the text content.
604
623
  */
605
- declare const wrapTool: <T extends SessionAuth, P extends SchemaParams>(tool: Tool<T, P>, telemetry: TelemetryCollector, captureConfig?: ToolCaptureConfig) => Tool<T, P>;
606
- declare const wrapResource: <T extends SessionAuth>(resource: Resource<T>, telemetry: TelemetryCollector) => Resource<T>;
607
- declare const wrapPrompt: <T extends SessionAuth, Args extends PromptArgument<T>[] = PromptArgument<T>[]>(prompt: Prompt<T, Args>, telemetry: TelemetryCollector) => Prompt<T, Args>;
624
+ export declare const wrapTool: <T extends SessionAuth, P extends SchemaParams>(tool: Tool<T, P>, telemetry: TelemetryCollector, captureConfig?: ToolCaptureConfig) => Tool<T, P>;
625
+ export declare const wrapResource: <T extends SessionAuth>(resource: Resource<T>, telemetry: TelemetryCollector) => Resource<T>;
626
+ export declare const wrapPrompt: <T extends SessionAuth, Args extends PromptArgument<T>[] = PromptArgument<T>[]>(prompt: Prompt<T, Args>, telemetry: TelemetryCollector) => Prompt<T, Args>;
608
627
  //#endregion
609
628
  //#region src/artifacts/ArtifactManager.d.ts
610
- declare const registerArtifacts: (app: Hono, artifacts: ReadonlyArray<ArtifactConfig>, authenticate?: ArtifactAuthenticate) => void;
629
+ export declare const registerArtifacts: (app: Hono, artifacts: ReadonlyArray<ArtifactConfig>, authenticate?: ArtifactAuthenticate) => void;
611
630
  //#endregion
612
631
  //#region src/artifacts/DashboardArtifact.d.ts
613
- declare const createDashboardArtifact: (getHealth: () => ServerHealth, getCapabilities: () => ServerCapabilities, getConnections: () => ReadonlyArray<GatewayInfo>) => ArtifactConfig;
632
+ export declare const createDashboardArtifact: (getHealth: () => ServerHealth, getCapabilities: () => ServerCapabilities, getConnections: () => ReadonlyArray<GatewayInfo>) => ArtifactConfig;
614
633
  //#endregion
615
634
  //#region src/artifacts/HealthArtifact.d.ts
616
- declare const DEFAULT_HEALTH_PATH = "/health";
617
- declare const DEFAULT_HEALTH_DETAIL_PATH = "/health/detail";
618
- declare const createHealthArtifact: (getHealth: () => ServerHealth, path?: string) => ArtifactConfig;
619
- declare const createHealthDetailArtifact: (getHealth: () => ServerHealth, path?: string) => ArtifactConfig;
635
+ export declare const DEFAULT_HEALTH_PATH = "/health";
636
+ export declare const DEFAULT_HEALTH_DETAIL_PATH = "/health/detail";
637
+ export declare const createHealthArtifact: (getHealth: () => ServerHealth, path?: string) => ArtifactConfig;
638
+ export declare const createHealthDetailArtifact: (getHealth: () => ServerHealth, path?: string) => ArtifactConfig;
620
639
  //#endregion
621
640
  //#region src/artifacts/InfoArtifact.d.ts
622
- declare const DEFAULT_INFO_PATH = "/info";
623
- declare const createInfoArtifact: (getInfo: () => ServerInfo, path?: string) => ArtifactConfig;
641
+ export declare const DEFAULT_INFO_PATH = "/info";
642
+ export declare const createInfoArtifact: (getInfo: () => ServerInfo, path?: string) => ArtifactConfig;
624
643
  //#endregion
625
644
  //#region src/introspection/capabilitiesTool.d.ts
626
- declare const createCapabilitiesTool: <T extends SessionAuth>(getCapabilities: () => ServerCapabilities) => Tool<T>;
645
+ export declare const createCapabilitiesTool: <T extends SessionAuth>(getCapabilities: () => ServerCapabilities) => Tool<T>;
627
646
  //#endregion
628
647
  //#region src/introspection/connectionsTool.d.ts
629
- declare const createConnectionsTool: <T extends SessionAuth>(getConnections: () => ReadonlyArray<GatewayInfo>) => Tool<T>;
648
+ export declare const createConnectionsTool: <T extends SessionAuth>(getConnections: () => ReadonlyArray<GatewayInfo>) => Tool<T>;
630
649
  //#endregion
631
650
  //#region src/introspection/healthTool.d.ts
632
- declare const createHealthTool: <T extends SessionAuth>(getHealth: () => ServerHealth) => Tool<T>;
651
+ export declare const createHealthTool: <T extends SessionAuth>(getHealth: () => ServerHealth) => Tool<T>;
633
652
  //#endregion
634
653
  //#region src/introspection/infoTool.d.ts
635
- declare const createInfoTool: <T extends SessionAuth>(getInfo: () => ServerInfo, name?: string) => Tool<T>;
654
+ export declare const createInfoTool: <T extends SessionAuth>(getInfo: () => ServerInfo, name?: string) => Tool<T>;
636
655
  //#endregion
637
656
  //#region src/feedback/redaction.d.ts
638
657
  type RedactionPattern = {
@@ -649,8 +668,8 @@ type RedactionResult = {
649
668
  redacted: boolean;
650
669
  text: string;
651
670
  };
652
- declare const DEFAULT_REDACTION_PATTERNS: ReadonlyArray<RedactionPattern>;
653
- declare const redact: (input: string, patterns?: ReadonlyArray<RedactionPattern>) => RedactionResult;
671
+ export declare const DEFAULT_REDACTION_PATTERNS: ReadonlyArray<RedactionPattern>;
672
+ export declare const redact: (input: string, patterns?: ReadonlyArray<RedactionPattern>) => RedactionResult;
654
673
  //#endregion
655
674
  //#region src/feedback/types.d.ts
656
675
  type FeedbackType = "bug" | "feature" | "feedback" | "question";
@@ -703,7 +722,7 @@ declare const PARAMETERS: z.ZodObject<{
703
722
  question: "question";
704
723
  }>>;
705
724
  }, z.core.$strip>;
706
- declare const createFeedbackTool: <T extends SessionAuth>(options: FeedbackToolOptions) => Tool<T, typeof PARAMETERS>;
725
+ export declare const createFeedbackTool: <T extends SessionAuth>(options: FeedbackToolOptions) => Tool<T, typeof PARAMETERS>;
707
726
  //#endregion
708
727
  //#region src/feedback/providers/github.d.ts
709
728
  type GithubFeedbackOptions = {
@@ -713,7 +732,7 @@ type GithubFeedbackOptions = {
713
732
  getToken: () => Option<string>;
714
733
  repo: `${string}/${string}`;
715
734
  };
716
- declare const createGithubFeedback: (options: GithubFeedbackOptions) => FeedbackProvider;
735
+ export declare const createGithubFeedback: (options: GithubFeedbackOptions) => FeedbackProvider;
717
736
  //#endregion
718
737
  //#region src/feedback/providers/webhook.d.ts
719
738
  type WebhookFeedbackOptions = {
@@ -722,16 +741,16 @@ type WebhookFeedbackOptions = {
722
741
  transform?: (payload: NormalizedFeedback) => unknown;
723
742
  url: string;
724
743
  };
725
- declare const createWebhookFeedback: (options: WebhookFeedbackOptions) => FeedbackProvider;
744
+ export declare const createWebhookFeedback: (options: WebhookFeedbackOptions) => FeedbackProvider;
726
745
  //#endregion
727
746
  //#region src/gateway/Gateway.d.ts
728
- declare const createGateway: (config: GatewayConfig, telemetry: TelemetryCollector) => GatewayInstance;
747
+ export declare const createGateway: (config: GatewayConfig, telemetry: TelemetryCollector) => GatewayInstance;
729
748
  //#endregion
730
749
  //#region src/gateway/GatewayManager.d.ts
731
- declare const createGatewayManager: (telemetry: TelemetryCollector) => GatewayManagerInstance;
750
+ export declare const createGatewayManager: (telemetry: TelemetryCollector) => GatewayManagerInstance;
732
751
  //#endregion
733
752
  //#region src/gateway/toolProxy.d.ts
734
- declare const createProxiedTools: <T extends SessionAuth>(gateway: GatewayInstance, telemetry?: TelemetryCollector) => ReadonlyArray<Tool<T>>;
753
+ export declare const createProxiedTools: <T extends SessionAuth>(gateway: GatewayInstance, telemetry?: TelemetryCollector) => ReadonlyArray<Tool<T>>;
735
754
  //#endregion
736
755
  //#region src/edge.d.ts
737
756
  /**
@@ -743,6 +762,6 @@ declare const createProxiedTools: <T extends SessionAuth>(gateway: GatewayInstan
743
762
  * export default { fetch: (req: Request) => server.fetch(req) }
744
763
  * ```
745
764
  */
746
- declare const createServer: <T extends SessionAuth = SessionAuth>(options: SomaServerOptions<T>) => SomaServerInstance<T>;
765
+ export declare const createServer: <T extends SessionAuth = SessionAuth>(options: SomaServerOptions<T>) => SomaServerInstance<T>;
747
766
  //#endregion
748
- export { type ArtifactAuthenticate, type ArtifactConfig, type AudioContent, type AuthMiddlewareConfig, type Authenticate, type BackendAdapter, type BackendFactory, type BackendSession, type BuildInfo, type CapabilitiesSummary, type CaptureLevel, type Completion, type Content, type ContentResult, type Context, DEFAULT_HEALTH_DETAIL_PATH, DEFAULT_HEALTH_PATH, DEFAULT_INFO_PATH, DEFAULT_REDACTION_PATTERNS, type DirectoryArtifact, type DynamicArtifact, type EdgeBackendOptions, type EnrichedErrorResponse, type ErrorCategory, type FeedbackEnrichmentContext, type FeedbackProvider, type FeedbackSeverity, type FeedbackSubmitFailure, type FeedbackSubmitResult, type FeedbackSubmitSuccess, type FeedbackToolOptions, type FeedbackType, type GatewayConfig, type GatewayInfo, type GatewayInstance, type GatewayManagerInstance, type GatewayStatus, type GithubFeedbackOptions, type HttpStreamConfig, type ImageContent, type InferSchemaOutput, type Logger, NoopTelemetry, type NormalizedFeedback, type OnUnauthorized, type Progress, type Prompt, type PromptArgument, type PromptResult, type RedactionPattern, type RedactionResult, type Resource, type ResourceContent, type ResourceLink, type ResourceResult, type RouteConfig, type RouteMethod, type RuntimeInfo, type SchemaParams, type ServerCapabilities, type ServerConfig, type ServerHealth, type ServerInfo, type ServerStatus, type SessionAuth, type SomaServerInstance, type SomaServerOptions, type StaticArtifact, type TelemetryCollector, type TelemetryEvent, type TelemetryEventType, type TextContent, type Tool, type ToolAnnotations, type ToolCaptureConfig, type ToolOptions, type TransportConfig, UserError, type WebhookFeedbackOptions, classifyError, createAuthMiddleware, createCapabilitiesTool, createCompositeTelemetry, createConnectionsTool, createConsoleTelemetry, createDashboardArtifact, createEdgeBackend, createEnrichedError, createFeedbackTool, createGateway, createGatewayManager, createGithubFeedback, createHealthArtifact, createHealthDetailArtifact, createHealthTool, createInfoArtifact, createInfoTool, createProxiedTools, createServer, createServerCore, createWebhookFeedback, getRequestHeader, getRuntimeInfo, readBuildInfoFromEnv, redact, registerArtifacts, resolveBuildInfo, wrapPrompt, wrapResource, wrapTool };
767
+ export type { ArtifactAuthenticate, ArtifactConfig, AudioContent, AuthMiddlewareConfig, Authenticate, BackendAdapter, BackendFactory, BackendSession, BuildInfo, CapabilitiesSummary, CaptureLevel, Completion, Content, ContentResult, Context, DirectoryArtifact, DynamicArtifact, EdgeBackendOptions, EnrichedErrorResponse, ErrorCategory, FeedbackEnrichmentContext, FeedbackProvider, FeedbackSeverity, FeedbackSubmitFailure, FeedbackSubmitResult, FeedbackSubmitSuccess, FeedbackToolOptions, FeedbackType, GatewayConfig, GatewayInfo, GatewayInstance, GatewayManagerInstance, GatewayStatus, GithubFeedbackOptions, HttpStreamConfig, ImageContent, InferSchemaOutput, Logger, NormalizedFeedback, OnUnauthorized, Progress, Prompt, PromptArgument, PromptResult, RedactionPattern, RedactionResult, Resource, ResourceContent, ResourceLink, ResourceResult, ResourceTemplate, ResourceTemplateArgument, RouteConfig, RouteMethod, RuntimeInfo, SchemaParams, ServerCapabilities, ServerConfig, ServerHealth, ServerInfo, ServerStatus, SessionAuth, SomaServerInstance, SomaServerOptions, StaticArtifact, TelemetryCollector, TelemetryEvent, TelemetryEventType, TextContent, Tool, ToolAnnotations, ToolCaptureConfig, ToolOptions, TransportConfig, WebhookFeedbackOptions };
@@ -1,3 +1,4 @@
1
+ import { Transport } from "@modelcontextprotocol/server";
1
2
  import { Hono } from "hono";
2
3
  //#region src/types/core.d.ts
3
4
  type SessionAuth = Record<string, unknown> | undefined;
@@ -129,6 +130,25 @@ type Resource<T extends SessionAuth = SessionAuth> = {
129
130
  name: string;
130
131
  uri: string;
131
132
  };
133
+ type ResourceTemplateArgument<T extends SessionAuth = SessionAuth> = Readonly<{
134
+ complete?: (value: string, auth?: T) => Promise<Completion>;
135
+ description?: string;
136
+ name: string;
137
+ required?: boolean;
138
+ }>;
139
+ /**
140
+ * A family of resources addressed by an RFC 6570 URI template, e.g. `docs://{path}`.
141
+ * `load` receives the variables matched from the requested URI.
142
+ */
143
+ type ResourceTemplate<T extends SessionAuth = SessionAuth> = {
144
+ arguments: ResourceTemplateArgument<T>[];
145
+ complete?: (name: string, value: string, auth?: T) => Promise<Completion>;
146
+ description?: string;
147
+ load: (args: Record<string, string>, auth?: T) => Promise<ResourceResult | ResourceResult[]>;
148
+ mimeType?: string;
149
+ name: string;
150
+ uriTemplate: string;
151
+ };
132
152
  type PromptArgument<T extends SessionAuth = SessionAuth> = Readonly<{
133
153
  complete?: (value: string, auth?: T) => Promise<Completion>;
134
154
  description?: string;
@@ -277,4 +297,28 @@ type BackendFactory<T extends SessionAuth = SessionAuth> = (config: ServerConfig
277
297
  //#region src/backend/fastmcp.d.ts
278
298
  declare const createFastMCPBackend: <T extends SessionAuth = SessionAuth>(config: ServerConfig<T>, backendOptions?: Record<string, unknown>) => BackendAdapter<T>;
279
299
  //#endregion
280
- export { ToolAnnotations as A, ResourceLink as C, SessionAuth as D, ServerStatus as E, TextContent as O, ResourceContent as S, SchemaParams as T, Progress as _, BackendSession as a, PromptResult as b, ServerConfig as c, Completion as d, Content as f, InferSchemaOutput as g, ImageContent as h, BackendFactory as i, UserError as j, Tool as k, TransportConfig as l, Context$1 as m, BackendAdapter as n, HttpStreamConfig as o, ContentResult as p, BackendEvents as r, Logger as s, createFastMCPBackend as t, AudioContent as u, Prompt as v, ResourceResult as w, Resource as x, PromptArgument as y };
300
+ //#region src/backend/sdk/index.d.ts
301
+ type SdkBackendOptions = {
302
+ /** MCP endpoint path when serving through `fetch`. `start({ httpStream: { endpoint } })` overrides it. Defaults to "/mcp". */
303
+ mcpPath?: string;
304
+ /**
305
+ * Transport for `start({ transportType: "stdio" })` in place of the process's
306
+ * stdin/stdout, e.g. a `StdioServerTransport` over a Unix socket.
307
+ */
308
+ stdioTransport?: Transport;
309
+ };
310
+ /**
311
+ * Backend built on the official MCP TypeScript SDK 2.x (`@modelcontextprotocol/server`).
312
+ *
313
+ * One endpoint serves both protocol eras: the `2026-07-28` revision that current
314
+ * Claude clients request first, and 2025-era clients (`initialize`). Serving is
315
+ * stateless: every request gets a fresh SDK server built from somamcp's registry,
316
+ * so there are no sessions, `connect`/`disconnect` never fire, and a 2025 client's
317
+ * GET or DELETE is answered `405`.
318
+ *
319
+ * `start()` serves a port (`httpStream`) or stdio on Node; `fetch()` serves any
320
+ * runtime with web-standard `Request`/`Response`.
321
+ */
322
+ declare const createSdkBackend: <T extends SessionAuth = SessionAuth>(config: ServerConfig<T>, backendOptions?: Record<string, unknown>) => BackendAdapter<T>;
323
+ //#endregion
324
+ export { ServerStatus as A, Resource as C, ResourceTemplate as D, ResourceResult as E, UserError as F, TextContent as M, Tool as N, ResourceTemplateArgument as O, ToolAnnotations as P, PromptResult as S, ResourceLink as T, ImageContent as _, BackendEvents as a, Prompt as b, HttpStreamConfig as c, TransportConfig as d, AudioContent as f, Context$1 as g, ContentResult as h, BackendAdapter as i, SessionAuth as j, SchemaParams as k, Logger as l, Content as m, createSdkBackend as n, BackendFactory as o, Completion as p, createFastMCPBackend as r, BackendSession as s, SdkBackendOptions as t, ServerConfig as u, InferSchemaOutput as v, ResourceContent as w, PromptArgument as x, Progress as y };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { A as ToolAnnotations, C as ResourceLink, D as SessionAuth, E as ServerStatus, O as TextContent, S as ResourceContent, T as SchemaParams, _ as Progress, a as BackendSession, b as PromptResult, c as ServerConfig, d as Completion, f as Content, g as InferSchemaOutput, h as ImageContent, i as BackendFactory, j as UserError, k as Tool, l as TransportConfig, m as Context, n as BackendAdapter, o as HttpStreamConfig, p as ContentResult, s as Logger, t as createFastMCPBackend, u as AudioContent, v as Prompt, w as ResourceResult, x as Resource, y as PromptArgument } from "./index-CSy9en2A.js";
1
+ import { A as ServerStatus, C as Resource, D as ResourceTemplate, E as ResourceResult, F as UserError, M as TextContent, N as Tool, O as ResourceTemplateArgument, P as ToolAnnotations, S as PromptResult, T as ResourceLink, _ as ImageContent, b as Prompt, c as HttpStreamConfig, d as TransportConfig, f as AudioContent, g as Context, h as ContentResult, i as BackendAdapter, j as SessionAuth, k as SchemaParams, l as Logger, m as Content, o as BackendFactory, p as Completion, r as createFastMCPBackend, s as BackendSession, u as ServerConfig, v as InferSchemaOutput, w as ResourceContent, x as PromptArgument, y as Progress } from "./index-C2wa9nmp.js";
2
2
  import { Option } from "functype";
3
+ import { Context as Context$1, Hono, MiddlewareHandler } from "hono";
3
4
  import { DirectLogger, DirectLogger as DirectLogger$1 } from "functype-log";
4
5
  import { z } from "zod";
5
- import { Context as Context$1, Hono, MiddlewareHandler } from "hono";
6
6
  import { Tool as Tool$1 } from "@modelcontextprotocol/sdk/types.js";
7
7
  //#region src/artifacts/types.d.ts
8
8
  type ArtifactCommon = {
@@ -41,9 +41,9 @@ type RuntimeInfo = {
41
41
  /** Which runtime family reported the fields above. Absent on pre-1.2 builds. */
42
42
  runtime?: "edge" | "node";
43
43
  };
44
- declare const readBuildInfoFromEnv: () => BuildInfo;
45
- declare const resolveBuildInfo: (override?: BuildInfo) => BuildInfo;
46
- declare const getRuntimeInfo: () => RuntimeInfo;
44
+ export declare const readBuildInfoFromEnv: () => BuildInfo;
45
+ export declare const resolveBuildInfo: (override?: BuildInfo) => BuildInfo;
46
+ export declare const getRuntimeInfo: () => RuntimeInfo;
47
47
  //#endregion
48
48
  //#region src/gateway/types.d.ts
49
49
  type GatewayConfig = {
@@ -128,7 +128,7 @@ type AuthMiddlewareConfig = {
128
128
  authenticate?: Authenticate;
129
129
  onUnauthorized?: OnUnauthorized;
130
130
  };
131
- declare const createAuthMiddleware: ({ authenticate, onUnauthorized }: AuthMiddlewareConfig) => MiddlewareHandler;
131
+ export declare const createAuthMiddleware: ({ authenticate, onUnauthorized }: AuthMiddlewareConfig) => MiddlewareHandler;
132
132
  //#endregion
133
133
  //#region src/auth/request.d.ts
134
134
  /**
@@ -143,7 +143,7 @@ declare const createAuthMiddleware: ({ authenticate, onUnauthorized }: AuthMiddl
143
143
  * absent or the request shape is not recognized — matches the `Headers.get`
144
144
  * shape callers already write against.
145
145
  */
146
- declare const getRequestHeader: (request: unknown, name: string) => string | undefined;
146
+ export declare const getRequestHeader: (request: unknown, name: string) => string | undefined;
147
147
  //#endregion
148
148
  //#region src/types/routes.d.ts
149
149
  type RouteMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
@@ -272,7 +272,7 @@ type SomaServerInstance<T extends SessionAuth = SessionAuth> = {
272
272
  * module — including `somamcp/edge`. The entry barrels supply the default instead:
273
273
  * `somamcp` binds createFastMCPBackend, `somamcp/edge` binds createEdgeBackend.
274
274
  */
275
- declare const createServerCore: <T extends SessionAuth = SessionAuth>(options: SomaServerOptions<T> & {
275
+ export declare const createServerCore: <T extends SessionAuth = SessionAuth>(options: SomaServerOptions<T> & {
276
276
  backend: BackendFactory<T>;
277
277
  }) => SomaServerInstance<T>;
278
278
  //#endregion
@@ -284,14 +284,14 @@ type ContentInput = {
284
284
  } | {
285
285
  url: string;
286
286
  };
287
- declare const imageContent: (input: ContentInput) => Promise<ImageContent>;
288
- declare const audioContent: (input: ContentInput) => Promise<AudioContent>;
287
+ export declare const imageContent: (input: ContentInput) => Promise<ImageContent>;
288
+ export declare const audioContent: (input: ContentInput) => Promise<AudioContent>;
289
289
  //#endregion
290
290
  //#region src/telemetry/CompositeTelemetry.d.ts
291
- declare const createCompositeTelemetry: (collectors: ReadonlyArray<TelemetryCollector>) => TelemetryCollector;
291
+ export declare const createCompositeTelemetry: (collectors: ReadonlyArray<TelemetryCollector>) => TelemetryCollector;
292
292
  //#endregion
293
293
  //#region src/telemetry/ConsoleTelemetry.d.ts
294
- declare const createConsoleTelemetry: (prefix?: string) => TelemetryCollector;
294
+ export declare const createConsoleTelemetry: (prefix?: string) => TelemetryCollector;
295
295
  //#endregion
296
296
  //#region src/telemetry/EnrichedError.d.ts
297
297
  type EnrichedErrorResponse = {
@@ -300,8 +300,8 @@ type EnrichedErrorResponse = {
300
300
  relatedState?: Record<string, unknown>;
301
301
  suggestions?: ReadonlyArray<string>;
302
302
  };
303
- declare const classifyError: (error: unknown) => ErrorCategory;
304
- declare const createEnrichedError: (error: unknown, context?: {
303
+ export declare const classifyError: (error: unknown) => ErrorCategory;
304
+ export declare const createEnrichedError: (error: unknown, context?: {
305
305
  gatewayStatus?: string;
306
306
  toolName?: string;
307
307
  }) => EnrichedErrorResponse;
@@ -311,13 +311,13 @@ type JsonFileTelemetryOptions = {
311
311
  filePath: string;
312
312
  flushIntervalMs?: number;
313
313
  };
314
- declare const createJsonFileTelemetry: (options: JsonFileTelemetryOptions) => TelemetryCollector;
314
+ export declare const createJsonFileTelemetry: (options: JsonFileTelemetryOptions) => TelemetryCollector;
315
315
  //#endregion
316
316
  //#region src/telemetry/LogLayerTelemetry.d.ts
317
- declare const createLogLayerTelemetry: (logger: DirectLogger$1) => TelemetryCollector;
317
+ export declare const createLogLayerTelemetry: (logger: DirectLogger$1) => TelemetryCollector;
318
318
  //#endregion
319
319
  //#region src/telemetry/NoopTelemetry.d.ts
320
- declare const NoopTelemetry: TelemetryCollector;
320
+ export declare const NoopTelemetry: TelemetryCollector;
321
321
  //#endregion
322
322
  //#region src/telemetry/telemetryWrapper.d.ts
323
323
  /**
@@ -333,40 +333,40 @@ declare const NoopTelemetry: TelemetryCollector;
333
333
  * The failure path converts an error to a `ContentResult` with `isError: true`
334
334
  * and the enriched error payload as the text content.
335
335
  */
336
- declare const wrapTool: <T extends SessionAuth, P extends SchemaParams>(tool: Tool<T, P>, telemetry: TelemetryCollector, captureConfig?: ToolCaptureConfig) => Tool<T, P>;
337
- declare const wrapResource: <T extends SessionAuth>(resource: Resource<T>, telemetry: TelemetryCollector) => Resource<T>;
338
- declare const wrapPrompt: <T extends SessionAuth, Args extends PromptArgument<T>[] = PromptArgument<T>[]>(prompt: Prompt<T, Args>, telemetry: TelemetryCollector) => Prompt<T, Args>;
336
+ export declare const wrapTool: <T extends SessionAuth, P extends SchemaParams>(tool: Tool<T, P>, telemetry: TelemetryCollector, captureConfig?: ToolCaptureConfig) => Tool<T, P>;
337
+ export declare const wrapResource: <T extends SessionAuth>(resource: Resource<T>, telemetry: TelemetryCollector) => Resource<T>;
338
+ export declare const wrapPrompt: <T extends SessionAuth, Args extends PromptArgument<T>[] = PromptArgument<T>[]>(prompt: Prompt<T, Args>, telemetry: TelemetryCollector) => Prompt<T, Args>;
339
339
  //#endregion
340
340
  //#region src/logging.d.ts
341
- declare const createDefaultLogger: (name: string) => DirectLogger$1;
341
+ export declare const createDefaultLogger: (name: string) => DirectLogger$1;
342
342
  //#endregion
343
343
  //#region src/artifacts/ArtifactManager.d.ts
344
- declare const registerArtifacts: (app: Hono, artifacts: ReadonlyArray<ArtifactConfig>, authenticate?: ArtifactAuthenticate) => void;
344
+ export declare const registerArtifacts: (app: Hono, artifacts: ReadonlyArray<ArtifactConfig>, authenticate?: ArtifactAuthenticate) => void;
345
345
  //#endregion
346
346
  //#region src/artifacts/DashboardArtifact.d.ts
347
- declare const createDashboardArtifact: (getHealth: () => ServerHealth, getCapabilities: () => ServerCapabilities, getConnections: () => ReadonlyArray<GatewayInfo>) => ArtifactConfig;
347
+ export declare const createDashboardArtifact: (getHealth: () => ServerHealth, getCapabilities: () => ServerCapabilities, getConnections: () => ReadonlyArray<GatewayInfo>) => ArtifactConfig;
348
348
  //#endregion
349
349
  //#region src/artifacts/HealthArtifact.d.ts
350
- declare const DEFAULT_HEALTH_PATH = "/health";
351
- declare const DEFAULT_HEALTH_DETAIL_PATH = "/health/detail";
352
- declare const createHealthArtifact: (getHealth: () => ServerHealth, path?: string) => ArtifactConfig;
353
- declare const createHealthDetailArtifact: (getHealth: () => ServerHealth, path?: string) => ArtifactConfig;
350
+ export declare const DEFAULT_HEALTH_PATH = "/health";
351
+ export declare const DEFAULT_HEALTH_DETAIL_PATH = "/health/detail";
352
+ export declare const createHealthArtifact: (getHealth: () => ServerHealth, path?: string) => ArtifactConfig;
353
+ export declare const createHealthDetailArtifact: (getHealth: () => ServerHealth, path?: string) => ArtifactConfig;
354
354
  //#endregion
355
355
  //#region src/artifacts/InfoArtifact.d.ts
356
- declare const DEFAULT_INFO_PATH = "/info";
357
- declare const createInfoArtifact: (getInfo: () => ServerInfo, path?: string) => ArtifactConfig;
356
+ export declare const DEFAULT_INFO_PATH = "/info";
357
+ export declare const createInfoArtifact: (getInfo: () => ServerInfo, path?: string) => ArtifactConfig;
358
358
  //#endregion
359
359
  //#region src/introspection/capabilitiesTool.d.ts
360
- declare const createCapabilitiesTool: <T extends SessionAuth>(getCapabilities: () => ServerCapabilities) => Tool<T>;
360
+ export declare const createCapabilitiesTool: <T extends SessionAuth>(getCapabilities: () => ServerCapabilities) => Tool<T>;
361
361
  //#endregion
362
362
  //#region src/introspection/connectionsTool.d.ts
363
- declare const createConnectionsTool: <T extends SessionAuth>(getConnections: () => ReadonlyArray<GatewayInfo>) => Tool<T>;
363
+ export declare const createConnectionsTool: <T extends SessionAuth>(getConnections: () => ReadonlyArray<GatewayInfo>) => Tool<T>;
364
364
  //#endregion
365
365
  //#region src/introspection/healthTool.d.ts
366
- declare const createHealthTool: <T extends SessionAuth>(getHealth: () => ServerHealth) => Tool<T>;
366
+ export declare const createHealthTool: <T extends SessionAuth>(getHealth: () => ServerHealth) => Tool<T>;
367
367
  //#endregion
368
368
  //#region src/introspection/infoTool.d.ts
369
- declare const createInfoTool: <T extends SessionAuth>(getInfo: () => ServerInfo, name?: string) => Tool<T>;
369
+ export declare const createInfoTool: <T extends SessionAuth>(getInfo: () => ServerInfo, name?: string) => Tool<T>;
370
370
  //#endregion
371
371
  //#region src/feedback/redaction.d.ts
372
372
  type RedactionPattern = {
@@ -383,8 +383,8 @@ type RedactionResult = {
383
383
  redacted: boolean;
384
384
  text: string;
385
385
  };
386
- declare const DEFAULT_REDACTION_PATTERNS: ReadonlyArray<RedactionPattern>;
387
- declare const redact: (input: string, patterns?: ReadonlyArray<RedactionPattern>) => RedactionResult;
386
+ export declare const DEFAULT_REDACTION_PATTERNS: ReadonlyArray<RedactionPattern>;
387
+ export declare const redact: (input: string, patterns?: ReadonlyArray<RedactionPattern>) => RedactionResult;
388
388
  //#endregion
389
389
  //#region src/feedback/types.d.ts
390
390
  type FeedbackType = "bug" | "feature" | "feedback" | "question";
@@ -437,7 +437,7 @@ declare const PARAMETERS: z.ZodObject<{
437
437
  question: "question";
438
438
  }>>;
439
439
  }, z.core.$strip>;
440
- declare const createFeedbackTool: <T extends SessionAuth>(options: FeedbackToolOptions) => Tool<T, typeof PARAMETERS>;
440
+ export declare const createFeedbackTool: <T extends SessionAuth>(options: FeedbackToolOptions) => Tool<T, typeof PARAMETERS>;
441
441
  //#endregion
442
442
  //#region src/feedback/providers/github.d.ts
443
443
  type GithubFeedbackOptions = {
@@ -447,7 +447,7 @@ type GithubFeedbackOptions = {
447
447
  getToken: () => Option<string>;
448
448
  repo: `${string}/${string}`;
449
449
  };
450
- declare const createGithubFeedback: (options: GithubFeedbackOptions) => FeedbackProvider;
450
+ export declare const createGithubFeedback: (options: GithubFeedbackOptions) => FeedbackProvider;
451
451
  //#endregion
452
452
  //#region src/feedback/providers/webhook.d.ts
453
453
  type WebhookFeedbackOptions = {
@@ -456,19 +456,19 @@ type WebhookFeedbackOptions = {
456
456
  transform?: (payload: NormalizedFeedback) => unknown;
457
457
  url: string;
458
458
  };
459
- declare const createWebhookFeedback: (options: WebhookFeedbackOptions) => FeedbackProvider;
459
+ export declare const createWebhookFeedback: (options: WebhookFeedbackOptions) => FeedbackProvider;
460
460
  //#endregion
461
461
  //#region src/gateway/Gateway.d.ts
462
- declare const createGateway: (config: GatewayConfig, telemetry: TelemetryCollector) => GatewayInstance;
462
+ export declare const createGateway: (config: GatewayConfig, telemetry: TelemetryCollector) => GatewayInstance;
463
463
  //#endregion
464
464
  //#region src/gateway/GatewayManager.d.ts
465
- declare const createGatewayManager: (telemetry: TelemetryCollector) => GatewayManagerInstance;
465
+ export declare const createGatewayManager: (telemetry: TelemetryCollector) => GatewayManagerInstance;
466
466
  //#endregion
467
467
  //#region src/gateway/toolProxy.d.ts
468
- declare const createProxiedTools: <T extends SessionAuth>(gateway: GatewayInstance, telemetry?: TelemetryCollector) => ReadonlyArray<Tool<T>>;
468
+ export declare const createProxiedTools: <T extends SessionAuth>(gateway: GatewayInstance, telemetry?: TelemetryCollector) => ReadonlyArray<Tool<T>>;
469
469
  //#endregion
470
470
  //#region src/index.d.ts
471
471
  /** Create a server backed by FastMCP (Node). For edge runtimes, use `somamcp/edge`. */
472
- declare const createServer: <T extends SessionAuth = SessionAuth>(options: SomaServerOptions<T>) => SomaServerInstance<T>;
472
+ export declare const createServer: <T extends SessionAuth = SessionAuth>(options: SomaServerOptions<T>) => SomaServerInstance<T>;
473
473
  //#endregion
474
- export { type ArtifactAuthenticate, type ArtifactConfig, type AudioContent, type AuthMiddlewareConfig, type Authenticate, type BackendAdapter, type BackendFactory, type BackendSession, type BuildInfo, type CapabilitiesSummary, type CaptureLevel, type Completion, type Content, type ContentResult, type Context, DEFAULT_HEALTH_DETAIL_PATH, DEFAULT_HEALTH_PATH, DEFAULT_INFO_PATH, DEFAULT_REDACTION_PATTERNS, type DirectLogger, type DirectoryArtifact, type DynamicArtifact, type EnrichedErrorResponse, type ErrorCategory, type FeedbackEnrichmentContext, type FeedbackProvider, type FeedbackSeverity, type FeedbackSubmitFailure, type FeedbackSubmitResult, type FeedbackSubmitSuccess, type FeedbackToolOptions, type FeedbackType, type GatewayConfig, type GatewayInfo, type GatewayInstance, type GatewayManagerInstance, type GatewayStatus, type GithubFeedbackOptions, type HttpStreamConfig, type ImageContent, type InferSchemaOutput, type JsonFileTelemetryOptions, type Logger, NoopTelemetry, type NormalizedFeedback, type OnUnauthorized, type Progress, type Prompt, type PromptArgument, type PromptResult, type RedactionPattern, type RedactionResult, type Resource, type ResourceContent, type ResourceLink, type ResourceResult, type RouteConfig, type RouteMethod, type RuntimeInfo, type SchemaParams, type ServerCapabilities, type ServerConfig, type ServerHealth, type ServerInfo, type ServerStatus, type SessionAuth, type SomaServerInstance, type SomaServerOptions, type StaticArtifact, type TelemetryCollector, type TelemetryEvent, type TelemetryEventType, type TextContent, type Tool, type ToolAnnotations, type ToolCaptureConfig, type ToolOptions, type TransportConfig, UserError, type WebhookFeedbackOptions, audioContent, classifyError, createAuthMiddleware, createCapabilitiesTool, createCompositeTelemetry, createConnectionsTool, createConsoleTelemetry, createDashboardArtifact, createDefaultLogger, createEnrichedError, createFastMCPBackend, createFeedbackTool, createGateway, createGatewayManager, createGithubFeedback, createHealthArtifact, createHealthDetailArtifact, createHealthTool, createInfoArtifact, createInfoTool, createJsonFileTelemetry, createLogLayerTelemetry, createProxiedTools, createServer, createServerCore, createWebhookFeedback, getRequestHeader, getRuntimeInfo, imageContent, readBuildInfoFromEnv, redact, registerArtifacts, resolveBuildInfo, wrapPrompt, wrapResource, wrapTool };
474
+ export { type ArtifactAuthenticate, type ArtifactConfig, type AudioContent, type AuthMiddlewareConfig, type Authenticate, type BackendAdapter, type BackendFactory, type BackendSession, type BuildInfo, type CapabilitiesSummary, type CaptureLevel, type Completion, type Content, type ContentResult, type Context, type DirectLogger, type DirectoryArtifact, type DynamicArtifact, type EnrichedErrorResponse, type ErrorCategory, type FeedbackEnrichmentContext, type FeedbackProvider, type FeedbackSeverity, type FeedbackSubmitFailure, type FeedbackSubmitResult, type FeedbackSubmitSuccess, type FeedbackToolOptions, type FeedbackType, type GatewayConfig, type GatewayInfo, type GatewayInstance, type GatewayManagerInstance, type GatewayStatus, type GithubFeedbackOptions, type HttpStreamConfig, type ImageContent, type InferSchemaOutput, type JsonFileTelemetryOptions, type Logger, type NormalizedFeedback, type OnUnauthorized, type Progress, type Prompt, type PromptArgument, type PromptResult, type RedactionPattern, type RedactionResult, type Resource, type ResourceContent, type ResourceLink, type ResourceResult, type ResourceTemplate, type ResourceTemplateArgument, type RouteConfig, type RouteMethod, type RuntimeInfo, type SchemaParams, type ServerCapabilities, type ServerConfig, type ServerHealth, type ServerInfo, type ServerStatus, type SessionAuth, type SomaServerInstance, type SomaServerOptions, type StaticArtifact, type TelemetryCollector, type TelemetryEvent, type TelemetryEventType, type TextContent, type Tool, type ToolAnnotations, type ToolCaptureConfig, type ToolOptions, type TransportConfig, UserError, type WebhookFeedbackOptions, createFastMCPBackend };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{t as e}from"./backend-Dd0n_9Ai.js";import{Map as t,Option as n,Ref as r,Set as i,Try as a,Tuple as o}from"functype";import{Client as s}from"@modelcontextprotocol/sdk/client/index.js";import{StreamableHTTPClientTransport as c}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{appendFile as l,mkdir as u,readFile as d}from"node:fs/promises";import{dirname as f,extname as p}from"node:path";import{createDirectConsoleLogger as m}from"functype-log";import{z as h}from"zod";const g=e=>e.json({error:`Unauthorized`},401),_=({authenticate:e,onUnauthorized:t})=>{let r=t??g;return async(t,i)=>{if(!e)return r(t);let o=n(t.env).flatMap(e=>n(e.incoming)).orElse(t.req.raw);if((await a.fromPromise(e(o))).isFailure())return r(t);await i()}},v=(e,t)=>typeof e.get==`function`?n(e.get(t)):n.none(),y=(e,t,r)=>{let i=e;return n(i[t]??i[r]).map(e=>Array.isArray(e)?e[0]??``:e)},b=(e,t,r)=>v(e,t).fold(()=>y(e,t,r),e=>n(e)),x=e=>n(e).flatMap(e=>n(e.headers)),S=(e,t)=>{let n=t.toLowerCase();return x(e).flatMap(e=>b(e,n,t)).orUndefined()},C=(e,t,n)=>{t.forEach(t=>{switch(t.protected&&e.use(t.path,_({authenticate:n})),t.type){case`static`:e.get(t.path,e=>e.body(t.content,{headers:{"Content-Type":t.contentType}}));break;case`dynamic`:e.get(t.path,e=>t.handler(e))}})},w=(e,t,n)=>({handler:()=>{let r=e(),i=t(),a=n(),o=T(r,i,a);return new Response(o,{headers:{"Content-Type":`text/html; charset=utf-8`}})},path:`/dashboard`,protected:!0,type:`dynamic`}),T=(e,t,n)=>`<!DOCTYPE html>
1
+ import{n as e}from"./backend-D0qSyfXw.js";import{Map as t,Option as n,Ref as r,Set as i,Try as a,Tuple as o}from"functype";import{Client as s}from"@modelcontextprotocol/sdk/client/index.js";import{StreamableHTTPClientTransport as c}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{appendFile as l,mkdir as u,readFile as d}from"node:fs/promises";import{dirname as f,extname as p}from"node:path";import{createDirectConsoleLogger as m}from"functype-log";import{z as h}from"zod";const g=e=>e.json({error:`Unauthorized`},401),_=({authenticate:e,onUnauthorized:t})=>{let r=t??g;return async(t,i)=>{if(!e)return r(t);let o=n(t.env).flatMap(e=>n(e.incoming)).orElse(t.req.raw);if((await a.fromPromise(e(o))).isFailure())return r(t);await i()}},v=(e,t)=>typeof e.get==`function`?n(e.get(t)):n.none(),y=(e,t,r)=>{let i=e;return n(i[t]??i[r]).map(e=>Array.isArray(e)?e[0]??``:e)},b=(e,t,r)=>v(e,t).fold(()=>y(e,t,r),e=>n(e)),x=e=>n(e).flatMap(e=>n(e.headers)),S=(e,t)=>{let n=t.toLowerCase();return x(e).flatMap(e=>b(e,n,t)).orUndefined()},C=(e,t,n)=>{t.forEach(t=>{switch(t.protected&&e.use(t.path,_({authenticate:n})),t.type){case`static`:e.get(t.path,e=>e.body(t.content,{headers:{"Content-Type":t.contentType}}));break;case`dynamic`:e.get(t.path,e=>t.handler(e))}})},w=(e,t,n)=>({handler:()=>{let r=e(),i=t(),a=n(),o=T(r,i,a);return new Response(o,{headers:{"Content-Type":`text/html; charset=utf-8`}})},path:`/dashboard`,protected:!0,type:`dynamic`}),T=(e,t,n)=>`<!DOCTYPE html>
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8">
@@ -0,0 +1 @@
1
+ const e=async(e,t)=>{let{serve:n}=await import(`@hono/node-server`),r=t.sslCert&&t.sslKey?(await import(`node:https`)).createServer:void 0;return new Promise((i,a)=>{let o=n({fetch:e.fetch,hostname:t.host??`localhost`,port:t.port,...r?{createServer:r,serverOptions:{ca:t.sslCa,cert:t.sslCert,key:t.sslKey}}:{}},()=>i({close:()=>new Promise((e,t)=>{o.close(n=>n?t(n):e()),`closeAllConnections`in o&&o.closeAllConnections()})}));o.once(`error`,a)})},t=async(e,t)=>{let{serveStdio:n}=await import(`@modelcontextprotocol/server/stdio`),r=n(e,t?{transport:t}:{});return{close:()=>r.close()}};export{e as listenHttp,t as listenStdio};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "somamcp",
3
- "version": "1.4.1",
3
+ "version": "1.5.1",
4
4
  "description": "Framework for building MCP servers with telemetry, introspection, and backend abstraction",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -59,19 +59,22 @@
59
59
  },
60
60
  "homepage": "https://github.com/sapientsai/SomaMCP#readme",
61
61
  "dependencies": {
62
- "@modelcontextprotocol/sdk": "^1.31.0",
63
- "fastmcp": "^4.22.1",
64
- "functype": "^1.12.0",
65
- "functype-log": "^1.12.0",
66
- "hono": "^4.13.12",
67
- "zod": "^4.6.5"
62
+ "@hono/node-server": "^2.1.5",
63
+ "@modelcontextprotocol/sdk": "^1.32.1",
64
+ "@modelcontextprotocol/server": "~2.3.1",
65
+ "fastmcp": "^4.23.5",
66
+ "functype": "^1.18.0",
67
+ "functype-log": "^1.18.0",
68
+ "hono": "^4.13.13",
69
+ "zod": "^4.6.7"
68
70
  },
69
71
  "prettier": "ts-builds/prettier",
70
72
  "devDependencies": {
71
- "@types/node": "^24.19.1",
73
+ "@modelcontextprotocol/client": "~2.3.1",
74
+ "@types/node": "^24.19.2",
72
75
  "get-port-please": "^3.2.0",
73
- "ts-builds": "^3.4.3",
74
- "tsdown": "^0.22.14"
76
+ "ts-builds": "^4.0.0",
77
+ "tsdown": "^0.23.1"
75
78
  },
76
- "packageManager": "pnpm@11.27.0+sha512.ad12821463bb143295f1fa3ecde77a6b9b97a7990386da800ff57bffc3964dc64b7b1c7559d5dbe5c337aea659ed9c8937d4370bd198ca2009bc6fa0249808e7"
79
+ "packageManager": "pnpm@11.28.6+sha512.55d90390c3b39042f1505a2697789f0256c6d95bb28bdd7cb731af1887c9f2629ef581acb9f4e4ec772024c8203c2aed22a03299b97103fdcf32668e905d0024"
77
80
  }
@@ -1 +0,0 @@
1
- import{FastMCP as e,ServerState as t}from"fastmcp";const n=e=>{switch(e){case t.Running:return`running`;case t.Error:return`error`;default:return`stopped`}},r=(t,r)=>{let i={...r,authenticate:t.authenticate,instructions:t.instructions,logger:t.logger,name:t.name,...t.streamKeepalive?{streamKeepalive:t.streamKeepalive}:{},version:t.version},a=new e(i);return{get serverState(){return n(a.serverState)},get sessions(){return a.sessions.map(e=>({sessionId:e.sessionId}))},addPrompt:e=>{a.addPrompt(e)},addResource:e=>{a.addResource(e)},addResourceTemplate:(...e)=>{a.addResourceTemplate(...e)},addTool:e=>{a.addTool(e)},fetch:async e=>a.getApp().fetch(e),getApp:()=>a.getApp(),on:(e,t)=>{a.on(e,t)},removePrompt:e=>a.removePrompt(e),removeResource:e=>a.removeResource(e),removeTool:e=>a.removeTool(e),start:async e=>{if(!e){await a.start();return}e.transportType===`httpStream`?await a.start({httpStream:e.httpStream,transportType:`httpStream`}):await a.start({transportType:`stdio`})},stop:()=>a.stop()}};export{r as t};