@haikit/mcp 0.0.0-stage → 0.33.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 hai contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,84 @@
1
- # Temporary Holding Version
1
+ # @haikit/mcp
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Call an MCP server's tools from inside your own HaiKIT tools.
4
+
5
+ The model never sees an MCP tool. You declare the server tools your app may
6
+ call, typed by schemas you own, and call them from a tool's `run` or an action
7
+ handler, as you would a database. Your tool decides what the model hears of
8
+ the result and what the browser shows. Nothing a third-party server says
9
+ reaches the model unless your code puts it there: not its tools' names or
10
+ descriptions, not its instructions, and not its results.
11
+
12
+ ```ts
13
+ import { mcpServer, http } from "@haikit/mcp";
14
+ import { defineTool } from "@haikit/core";
15
+ import { z } from "zod";
16
+
17
+ const github = mcpServer({
18
+ name: "github",
19
+ transport: http("https://api.example.com/mcp", { headers: { Authorization: `Bearer ${token}` } }),
20
+ });
21
+
22
+ // each server tool the app may call, checked both ways by your schemas
23
+ const searchIssues = github.tool("search_issues", {
24
+ args: z.object({ q: z.string(), per_page: z.number() }),
25
+ result: z.object({ items: z.array(Issue) }),
26
+ });
27
+
28
+ // what the model sees is yours: the name, the description, the schema
29
+ export const findIssues = defineTool({
30
+ name: "find_issues",
31
+ description: "Search this project's issues.",
32
+ input: z.object({ query: z.string() }),
33
+ inputJsonSchema: { type: "object", properties: { query: { type: "string" } }, required: ["query"] },
34
+ async run({ query }, ctx) {
35
+ const { items } = await searchIssues.call({ q: `repo:acme/app ${query}`, per_page: 50 }, ctx);
36
+ return ctx.render(issueList, { issues: items }); // rows to the browser, the digest to the model
37
+ },
38
+ });
39
+
40
+ await github.connect(); // at startup: stops here if a declared tool isn't on the server
41
+ ```
42
+
43
+ - `stdio({ command, args })` starts a local server as a child process instead.
44
+ The child gets only a short list of safe environment variables, not yours.
45
+ - A call throws `McpToolError` when the tool reports an error, and `McpError`
46
+ when there's no result: bad args, a result your schema refuses, a timeout,
47
+ a lost connection, a refusal. The message names only the server and the
48
+ tool. What the server said is on `err.text`, so a tool that lets the error
49
+ through doesn't pass the server's words to the model.
50
+ - Progress from the server reaches `ctx.progress`, and keeps a long call alive.
51
+ A call times out after 30 s without word from the server, and after 90 s in
52
+ all, connecting included, inside the 120 s turn lease.
53
+ - `textOf(result)` turns a result into text, for a tool that decides to pass
54
+ some of it on. A cut is always marked in the text.
55
+
56
+ A server can take each user's own credential instead of the app's. Then each
57
+ call runs as the conversation's owner, over a connection of their own:
58
+
59
+ ```ts
60
+ import { createMcpAuth } from "@haikit/mcp";
61
+
62
+ const mcpAuth = createMcpAuth({ userOf: (id) => auth.ownerOf(id) }); // auth from @haikit/auth
63
+ const tracker = mcpServer({
64
+ name: "tracker",
65
+ transport: http("https://mcp.tracker.example/mcp"),
66
+ auth: mcpAuth.bearer((userId) => keys.find(userId)), // their token, or null
67
+ });
68
+ ```
69
+
70
+ A call with no one to run as is refused with reason `user`, and one for a user
71
+ with no token with reason `auth`, before anything is sent: it never falls
72
+ back to the app's identity. `err.auth.kind` says what the user must do:
73
+ `connect`, `reconnect`, or grant more `scope`. A job outside any conversation
74
+ passes `{ userId }`.
75
+
76
+ `McpTool` isn't a HaiKIT `Tool`, so it can't be passed to
77
+ `createHai({ tools })`: `npm run typetest` checks that.
78
+
79
+ Imports only `@haikit/core`, never `@haikit/server`. Built on
80
+ [`@modelcontextprotocol/client`](https://www.npmjs.com/package/@modelcontextprotocol/client),
81
+ the official TypeScript SDK's client.
82
+
83
+ Everything it does, with every default and message:
84
+ [the reference manual](https://github.com/wfoxd/haikit/blob/main/docs/reference/mcp.md).
package/dist/auth.d.ts ADDED
@@ -0,0 +1,80 @@
1
+ import type { AuthProvider } from "@modelcontextprotocol/client";
2
+ export interface McpAuthOptions {
3
+ /**
4
+ * Who a conversation belongs to: the user a call made in it runs as. With
5
+ * @haikit/auth, `(id) => auth.ownerOf(id)`. `null` for no one.
6
+ */
7
+ userOf(conversationId: string): string | null | Promise<string | null>;
8
+ }
9
+ /** Makes the `auth` of servers whose calls are made as each user. */
10
+ export interface McpAuth {
11
+ /**
12
+ * Each user's own token, which the app already has: `token(userId)` gives
13
+ * it, or `null` when the user has none. Sent as `Authorization: Bearer`.
14
+ */
15
+ bearer(token: (userId: string) => string | null | Promise<string | null>): McpServerAuth;
16
+ }
17
+ /** How a server's calls are made as each user: made by an `McpAuth`, and given to `mcpServer({ auth })`. */
18
+ export interface McpServerAuth {
19
+ readonly kind: "bearer";
20
+ }
21
+ /** What an `McpServerAuth` stands for. */
22
+ export interface AuthConfig {
23
+ readonly kind: "bearer";
24
+ userOf(conversationId: string): string | null | Promise<string | null>;
25
+ token(userId: string): string | null | Promise<string | null>;
26
+ /** Server names in use with this `McpAuth`: each is a key for its users' credentials. */
27
+ readonly names: Set<string>;
28
+ }
29
+ /** The config an `McpServerAuth` stands for, or undefined if `createMcpAuth` didn't make it. */
30
+ export declare const configOf: (auth: unknown) => AuthConfig | undefined;
31
+ /**
32
+ * For servers whose calls are made as each user, with that user's own
33
+ * credential: `mcpServer({ auth: mcpAuth.bearer(token) })`.
34
+ */
35
+ export declare function createMcpAuth(options: McpAuthOptions): McpAuth;
36
+ /**
37
+ * The user has no credential, or the server refused theirs: thrown inside a
38
+ * connection, where the transport passes it on unchanged, and made an
39
+ * `McpError` with reason `auth`.
40
+ */
41
+ export declare class NeedsAuth extends Error {
42
+ readonly kind: "connect" | "reconnect";
43
+ readonly name = "NeedsAuth";
44
+ constructor(kind: "connect" | "reconnect");
45
+ }
46
+ /** The app's lookup of a credential failed: made an `McpError` with reason `connection`. */
47
+ export declare class LookupFailed extends Error {
48
+ readonly name = "LookupFailed";
49
+ constructor(cause: unknown);
50
+ }
51
+ /** One user's credential for one server, and the `AuthProvider` that sends it. */
52
+ export interface Credential {
53
+ /** Before a connection or call: finds the credential, or throws `NeedsAuth("connect")`, so nothing is sent without one. */
54
+ ensure(): Promise<void>;
55
+ /** For a connection being closed: stops a lookup on its way, and its timer. */
56
+ close(): void;
57
+ readonly provider: AuthProvider;
58
+ }
59
+ /** A token from `bearer`'s function, kept until a lookup on a 401 finds another, or none. */
60
+ export declare class BearerCredential implements Credential {
61
+ private readonly read;
62
+ private readonly user;
63
+ /** How long `read` may take: a lookup that never answers would hold up every call after it. */
64
+ private readonly timeoutMs;
65
+ private token;
66
+ /** The lookup on its way, which every caller shares: only it sets `token`. */
67
+ private looking;
68
+ /** Stops the lookup on its way, for `close()`. */
69
+ private stop;
70
+ constructor(read: (userId: string) => string | null | Promise<string | null>, user: string,
71
+ /** How long `read` may take: a lookup that never answers would hold up every call after it. */
72
+ timeoutMs: number);
73
+ ensure(): Promise<void>;
74
+ close(): void;
75
+ readonly provider: AuthProvider;
76
+ /** One lookup at a time, for first calls and 401s that come together, so none overwrites another's token. */
77
+ private look;
78
+ private lookup;
79
+ }
80
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,MAAM,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACxE;AAED,qEAAqE;AACrE,MAAM,WAAW,OAAO;IACtB;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,aAAa,CAAC;CAC1F;AAED,4GAA4G;AAC5G,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;CACzB;AAED,0CAA0C;AAC1C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,MAAM,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACvE,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9D,yFAAyF;IACzF,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC7B;AAID,gGAAgG;AAChG,eAAO,MAAM,QAAQ,GAAI,MAAM,OAAO,KAAG,UAAU,GAAG,SACqB,CAAC;AAE5E;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAgB9D;AAED;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAEtB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,WAAW;IADlD,QAAQ,CAAC,IAAI,eAAe;gBACP,IAAI,EAAE,SAAS,GAAG,WAAW;CAGnD;AAED,4FAA4F;AAC5F,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,kBAAkB;gBACnB,KAAK,EAAE,OAAO;CAG3B;AAED,kFAAkF;AAClF,MAAM,WAAW,UAAU;IACzB,2HAA2H;IAC3H,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,+EAA+E;IAC/E,KAAK,IAAI,IAAI,CAAC;IACd,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;CACjC;AAED,6FAA6F;AAC7F,qBAAa,gBAAiB,YAAW,UAAU;IAQ/C,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,+FAA+F;IAC/F,OAAO,CAAC,QAAQ,CAAC,SAAS;IAV5B,OAAO,CAAC,KAAK,CAAuB;IACpC,8EAA8E;IAC9E,OAAO,CAAC,OAAO,CAAuC;IACtD,kDAAkD;IAClD,OAAO,CAAC,IAAI,CAA6B;gBAGtB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,EAChE,IAAI,EAAE,MAAM;IAC7B,+FAA+F;IAC9E,SAAS,EAAE,MAAM;IAG9B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAK7B,KAAK,IAAI,IAAI;IAMb,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAc7B;IAEF,6GAA6G;IAC7G,OAAO,CAAC,IAAI;YASE,MAAM;CAiBrB"}
package/dist/auth.js ADDED
@@ -0,0 +1,119 @@
1
+ const configs = new WeakMap();
2
+ /** The config an `McpServerAuth` stands for, or undefined if `createMcpAuth` didn't make it. */
3
+ export const configOf = (auth) => typeof auth === "object" && auth !== null ? configs.get(auth) : undefined;
4
+ /**
5
+ * For servers whose calls are made as each user, with that user's own
6
+ * credential: `mcpServer({ auth: mcpAuth.bearer(token) })`.
7
+ */
8
+ export function createMcpAuth(options) {
9
+ if (typeof options?.userOf !== "function") {
10
+ throw new TypeError("createMcpAuth: userOf must be a function, such as (id) => auth.ownerOf(id)");
11
+ }
12
+ const names = new Set();
13
+ const userOf = (conversationId) => options.userOf(conversationId);
14
+ return Object.freeze({
15
+ bearer(token) {
16
+ if (typeof token !== "function") {
17
+ throw new TypeError("bearer: token must be a function that takes a user id and returns their token, or null");
18
+ }
19
+ const auth = Object.freeze({ kind: "bearer" });
20
+ configs.set(auth, { kind: "bearer", userOf, token, names });
21
+ return auth;
22
+ },
23
+ });
24
+ }
25
+ /**
26
+ * The user has no credential, or the server refused theirs: thrown inside a
27
+ * connection, where the transport passes it on unchanged, and made an
28
+ * `McpError` with reason `auth`.
29
+ */
30
+ export class NeedsAuth extends Error {
31
+ kind;
32
+ name = "NeedsAuth";
33
+ constructor(kind) {
34
+ super(kind === "connect" ? "the user has no credential" : "the server refused the user's credential");
35
+ this.kind = kind;
36
+ }
37
+ }
38
+ /** The app's lookup of a credential failed: made an `McpError` with reason `connection`. */
39
+ export class LookupFailed extends Error {
40
+ name = "LookupFailed";
41
+ constructor(cause) {
42
+ super("the user's credential could not be looked up", { cause });
43
+ }
44
+ }
45
+ /** A token from `bearer`'s function, kept until a lookup on a 401 finds another, or none. */
46
+ export class BearerCredential {
47
+ read;
48
+ user;
49
+ timeoutMs;
50
+ token = null;
51
+ /** The lookup on its way, which every caller shares: only it sets `token`. */
52
+ looking = null;
53
+ /** Stops the lookup on its way, for `close()`. */
54
+ stop = null;
55
+ constructor(read, user,
56
+ /** How long `read` may take: a lookup that never answers would hold up every call after it. */
57
+ timeoutMs) {
58
+ this.read = read;
59
+ this.user = user;
60
+ this.timeoutMs = timeoutMs;
61
+ }
62
+ async ensure() {
63
+ if (this.token === null)
64
+ await this.look();
65
+ if (this.token === null)
66
+ throw new NeedsAuth("connect");
67
+ }
68
+ close() {
69
+ this.stop?.();
70
+ }
71
+ // The transport asks for the token before every request, and on a 401
72
+ // calls onUnauthorized, then tries once more with what it finds.
73
+ provider = {
74
+ // A request is never sent without the user's token: the transport would
75
+ // send it with no Authorization at all. Gone since its call began, as
76
+ // when another call's 401 found none, it stops the request here.
77
+ token: async () => {
78
+ if (this.token === null)
79
+ throw new NeedsAuth("reconnect");
80
+ return this.token;
81
+ },
82
+ onUnauthorized: async () => {
83
+ // A token the server still refuses gets its 401 on the retry, and is
84
+ // kept: the next 401 looks again. Forgetting it would throw away a
85
+ // newer one that another call's 401 found meanwhile.
86
+ if ((await this.look()) === null)
87
+ throw new NeedsAuth("reconnect");
88
+ },
89
+ };
90
+ /** One lookup at a time, for first calls and 401s that come together, so none overwrites another's token. */
91
+ look() {
92
+ this.looking ??= this.lookup()
93
+ .then((token) => (this.token = token))
94
+ .finally(() => {
95
+ this.looking = null;
96
+ });
97
+ return this.looking;
98
+ }
99
+ async lookup() {
100
+ let timer;
101
+ const cut = new Promise((_, reject) => {
102
+ timer = setTimeout(() => reject(new Error(`no token within ${this.timeoutMs} ms`)), this.timeoutMs);
103
+ this.stop = () => reject(new Error("closed while the token was being looked up"));
104
+ });
105
+ let token;
106
+ try {
107
+ token = await Promise.race([Promise.resolve().then(() => this.read(this.user)), cut]);
108
+ }
109
+ catch (err) {
110
+ throw new LookupFailed(err);
111
+ }
112
+ finally {
113
+ clearTimeout(timer);
114
+ this.stop = null;
115
+ }
116
+ return typeof token === "string" && token !== "" ? token : null;
117
+ }
118
+ }
119
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import type { ContentBlock } from "@modelcontextprotocol/client";
2
+ /**
3
+ * Why a call failed:
4
+ *
5
+ * - `args`: the args didn't match the tool's `args` schema, so nothing was sent.
6
+ * - `result`: the result didn't match its `result` schema.
7
+ * - `timeout`: the server didn't answer within `timeoutMs` or `maxTotalMs`.
8
+ * - `connection`: the server couldn't be reached, or the connection dropped.
9
+ * - `protocol`: the server refused the call, such as for a tool it doesn't
10
+ * have, or asked for something this client doesn't do.
11
+ * - `closed`: `close()` was called.
12
+ * - `user`: a server with `auth` had no user to call as, so nothing was sent.
13
+ * - `auth`: the user's credential for the server is missing, was refused, or
14
+ * needs more access. `auth` on the error says which.
15
+ */
16
+ export type McpErrorReason = "args" | "result" | "timeout" | "connection" | "protocol" | "closed" | "user" | "auth";
17
+ /** What a call with reason `auth` needs from the user. */
18
+ export interface McpAuthNeed {
19
+ /**
20
+ * `connect`: the user has no credential for the server, so nothing was sent.
21
+ * `reconnect`: the server refused theirs. `scope`: theirs needs more access.
22
+ */
23
+ readonly kind: "connect" | "reconnect" | "scope";
24
+ /** On `scope`: the scope the server asked for, as its challenge put it. */
25
+ readonly scope?: string;
26
+ }
27
+ /**
28
+ * A call that didn't get a result. The message names only the server and the
29
+ * tool, never what the server said: a HaiKIT tool that lets this go reaches the
30
+ * model as `<name> failed: <message>`, and the server's words aren't the app's
31
+ * to pass on unread. Its words are on `text`, for logs and for code that
32
+ * decides.
33
+ *
34
+ * Detected by `name` rather than `instanceof`, as in @haikit/core: a duplicated
35
+ * install would give two distinct classes.
36
+ */
37
+ export declare class McpError extends Error {
38
+ readonly name = "McpError";
39
+ /** The server's `name`. */
40
+ readonly server: string;
41
+ /** The tool called. Absent when `connect()` failed. */
42
+ readonly tool: string | undefined;
43
+ readonly reason: McpErrorReason;
44
+ /** What the server said about it, when it said anything: a JSON-RPC error's message. */
45
+ readonly text: string | undefined;
46
+ /** A JSON-RPC error's code. */
47
+ readonly code: number | undefined;
48
+ /** With reason `auth`: what the user's credential needs. */
49
+ readonly auth: McpAuthNeed | undefined;
50
+ constructor(reason: McpErrorReason, message: string, detail: {
51
+ server: string;
52
+ tool?: string;
53
+ text?: string;
54
+ code?: number;
55
+ cause?: unknown;
56
+ auth?: McpAuthNeed;
57
+ });
58
+ }
59
+ /**
60
+ * The tool ran and reported an error (`isError` in its result). Its message
61
+ * says only that, for the reason `McpError`'s does; what the server said is on
62
+ * `text` and `content`.
63
+ */
64
+ export declare class McpToolError extends Error {
65
+ readonly name = "McpToolError";
66
+ readonly server: string;
67
+ readonly tool: string;
68
+ /** The result's text blocks, joined by newlines. */
69
+ readonly text: string;
70
+ /** The result's content blocks, as the server sent them. */
71
+ readonly content: ContentBlock[];
72
+ constructor(server: string, tool: string, content: ContentBlock[]);
73
+ }
74
+ export declare const isMcpError: (err: unknown) => err is McpError;
75
+ export declare const isMcpToolError: (err: unknown) => err is McpToolError;
76
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpH,0DAA0D;AAC1D,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACjD,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,cAAc;IAC3B,2BAA2B;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,wFAAwF;IACxF,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,+BAA+B;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,CAAC;gBAGrC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,WAAW,CAAA;KAAE;CAU/G;AAED;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,kBAAkB;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;gBAErB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE;CAOlE;AAED,eAAO,MAAM,UAAU,GAAI,KAAK,OAAO,KAAG,GAAG,IAAI,QAA2D,CAAC;AAE7G,eAAO,MAAM,cAAc,GAAI,KAAK,OAAO,KAAG,GAAG,IAAI,YACA,CAAC"}
package/dist/errors.js ADDED
@@ -0,0 +1,57 @@
1
+ /**
2
+ * A call that didn't get a result. The message names only the server and the
3
+ * tool, never what the server said: a HaiKIT tool that lets this go reaches the
4
+ * model as `<name> failed: <message>`, and the server's words aren't the app's
5
+ * to pass on unread. Its words are on `text`, for logs and for code that
6
+ * decides.
7
+ *
8
+ * Detected by `name` rather than `instanceof`, as in @haikit/core: a duplicated
9
+ * install would give two distinct classes.
10
+ */
11
+ export class McpError extends Error {
12
+ name = "McpError";
13
+ /** The server's `name`. */
14
+ server;
15
+ /** The tool called. Absent when `connect()` failed. */
16
+ tool;
17
+ reason;
18
+ /** What the server said about it, when it said anything: a JSON-RPC error's message. */
19
+ text;
20
+ /** A JSON-RPC error's code. */
21
+ code;
22
+ /** With reason `auth`: what the user's credential needs. */
23
+ auth;
24
+ constructor(reason, message, detail) {
25
+ super(message, detail.cause === undefined ? undefined : { cause: detail.cause });
26
+ this.reason = reason;
27
+ this.server = detail.server;
28
+ this.tool = detail.tool;
29
+ this.text = detail.text;
30
+ this.code = detail.code;
31
+ this.auth = detail.auth === undefined ? undefined : Object.freeze({ ...detail.auth });
32
+ }
33
+ }
34
+ /**
35
+ * The tool ran and reported an error (`isError` in its result). Its message
36
+ * says only that, for the reason `McpError`'s does; what the server said is on
37
+ * `text` and `content`.
38
+ */
39
+ export class McpToolError extends Error {
40
+ name = "McpToolError";
41
+ server;
42
+ tool;
43
+ /** The result's text blocks, joined by newlines. */
44
+ text;
45
+ /** The result's content blocks, as the server sent them. */
46
+ content;
47
+ constructor(server, tool, content) {
48
+ super(`${server}/${tool} reported an error`);
49
+ this.server = server;
50
+ this.tool = tool;
51
+ this.content = content;
52
+ this.text = content.flatMap((b) => (b.type === "text" ? [b.text] : [])).join("\n");
53
+ }
54
+ }
55
+ export const isMcpError = (err) => err instanceof Error && err.name === "McpError";
56
+ export const isMcpToolError = (err) => err instanceof Error && err.name === "McpToolError";
57
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AA6BA;;;;;;;;;GASG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,GAAG,UAAU,CAAC;IAC3B,2BAA2B;IAClB,MAAM,CAAS;IACxB,uDAAuD;IAC9C,IAAI,CAAqB;IACzB,MAAM,CAAiB;IAChC,wFAAwF;IAC/E,IAAI,CAAqB;IAClC,+BAA+B;IACtB,IAAI,CAAqB;IAClC,4DAA4D;IACnD,IAAI,CAA0B;IAEvC,YACE,MAAsB,EACtB,OAAe,EACf,MAA4G;QAE5G,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACjF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACxF,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IAC5B,IAAI,GAAG,cAAc,CAAC;IACtB,MAAM,CAAS;IACf,IAAI,CAAS;IACtB,oDAAoD;IAC3C,IAAI,CAAS;IACtB,4DAA4D;IACnD,OAAO,CAAiB;IAEjC,YAAY,MAAc,EAAE,IAAY,EAAE,OAAuB;QAC/D,KAAK,CAAC,GAAG,MAAM,IAAI,IAAI,oBAAoB,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrF,CAAC;CACF;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAY,EAAmB,EAAE,CAAC,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC;AAE7G,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAY,EAAuB,EAAE,CAClE,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,CAAC"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * @haikit/mcp — call MCP servers' tools from inside your own tools.
3
+ *
4
+ * The model never sees an MCP tool. An app declares the server tools it calls,
5
+ * typed by schemas it owns, and calls them from a HaiKIT tool's `run` or an
6
+ * action handler, the way it would call a database: that code decides what the
7
+ * model hears of a result and what the browser shows. So nothing a third-party
8
+ * server says — its tools' names and descriptions, its instructions, its
9
+ * results — reaches the model unless app code puts it there.
10
+ *
11
+ * There is no way to make a HaiKIT `Tool` from an MCP tool here, on purpose:
12
+ * an `McpTool` has no `run`, so `createHai({ tools })` won't take one.
13
+ *
14
+ * Imports only @haikit/core, like the model adapters.
15
+ */
16
+ import type { Progress, Schema } from "@haikit/core";
17
+ import { type AuthProvider, type ContentBlock, type Transport, type VersionNegotiationMode } from "@modelcontextprotocol/client";
18
+ import { type McpServerAuth } from "./auth.js";
19
+ export { createMcpAuth, type McpAuth, type McpAuthOptions, type McpServerAuth } from "./auth.js";
20
+ export { McpError, McpToolError, isMcpError, isMcpToolError, type McpAuthNeed, type McpErrorReason } from "./errors.js";
21
+ export { textOf, type TextOptions } from "./text.js";
22
+ export { http, stdio, type HttpOptions } from "./transports.js";
23
+ export type { AuthProvider, ContentBlock, Transport } from "@modelcontextprotocol/client";
24
+ export interface McpServerOptions {
25
+ /** Names the server in errors and warnings, as in `github/search_issues`. */
26
+ name: string;
27
+ /**
28
+ * Makes a connection: called by the first `connect()` or call, and again
29
+ * for each reconnect. `http(url)` and `stdio({ command })` make one. For a
30
+ * server with `auth`, it's given the user's `AuthProvider`, and must be
31
+ * `http()`'s.
32
+ */
33
+ transport: (authProvider?: AuthProvider) => Transport | Promise<Transport>;
34
+ /**
35
+ * Makes each call as the user it runs for, with their own credential, over
36
+ * a connection of their own: `createMcpAuth({ userOf }).bearer(token)`.
37
+ * Without it, every call shares one connection and one identity.
38
+ */
39
+ auth?: McpServerAuth;
40
+ /**
41
+ * With `auth`: the most users connected at once. Past it, the least recently
42
+ * used connection with no call in flight is closed. Default 100.
43
+ */
44
+ maxConnections?: number;
45
+ /** With `auth`: a user's connection is closed after this long with no call, in milliseconds. Default 300,000. */
46
+ idleMs?: number;
47
+ /**
48
+ * How long the server may go without answering a call or reporting progress
49
+ * on it, in milliseconds. Also bounds making the transport, connecting,
50
+ * listing tools and, with `auth`, looking up a user's token. Default 30,000.
51
+ */
52
+ timeoutMs?: number;
53
+ /**
54
+ * The longest a call may take, progress or not, connecting included, in
55
+ * milliseconds. Default 90,000.
56
+ */
57
+ maxTotalMs?: number;
58
+ /**
59
+ * A declared tool was removed from the server, or its schema changed: seen
60
+ * when the server says its tools changed, and on a reconnect. Calls go on
61
+ * as before; one to a removed tool fails. Default: a `console.warn`. If it
62
+ * throws, the error is logged with `console.error`.
63
+ */
64
+ onChange?: (change: McpToolChange) => void;
65
+ /** The SDK's protocol version negotiation. Default `"legacy"`, the SDK's own: the 2025 handshake. */
66
+ versionNegotiation?: VersionNegotiationMode;
67
+ }
68
+ export interface McpToolChange {
69
+ server: string;
70
+ /** With `auth`: the user whose connection saw the change. Each user's tools are compared apart. */
71
+ user?: string;
72
+ /** Declared tools the server no longer has. */
73
+ removed: string[];
74
+ /** Declared tools whose input or output schema, or task support, changed. */
75
+ changed: string[];
76
+ }
77
+ export interface McpToolDef<A, R> {
78
+ /** Checks the args before anything is sent. They must come out an object. */
79
+ args: Schema<A>;
80
+ /**
81
+ * Checks the result, which `call` then resolves to: the server's structured
82
+ * result, or, without one, the JSON in its one text block. Without this,
83
+ * `call` resolves to the result's content as the server sent it.
84
+ */
85
+ result?: Schema<R>;
86
+ /** Overrides the server's `timeoutMs` for this tool. */
87
+ timeoutMs?: number;
88
+ /** Overrides the server's `maxTotalMs` for this tool. */
89
+ maxTotalMs?: number;
90
+ }
91
+ /** A result with no `result` schema: what the server sent, unchecked. */
92
+ export interface McpResult {
93
+ /** The content blocks, as the server sent them. */
94
+ content: ContentBlock[];
95
+ /** The server's structured result, when it sent one. */
96
+ structuredContent?: unknown;
97
+ }
98
+ /**
99
+ * What a call is made for. A HaiKIT tool's `ctx` or an action handler's can
100
+ * be passed as it is.
101
+ */
102
+ export interface McpCallCtx {
103
+ /**
104
+ * The conversation the call is for. A server with `auth` calls as its
105
+ * owner, from `userOf`.
106
+ */
107
+ readonly conversationId?: string;
108
+ /**
109
+ * For a server with `auth`: the user to call as, for a call made outside any
110
+ * conversation, such as a job. With a `conversationId` too, it must be the
111
+ * conversation's owner.
112
+ */
113
+ readonly userId?: string;
114
+ /** Hears the server's progress notifications, as `ToolCtx.progress` does. */
115
+ progress?(progress: Progress): void;
116
+ }
117
+ /** One of the server's tools, as the app declared it. Not a HaiKIT `Tool`: the model never sees it. */
118
+ export interface McpTool<A, R> {
119
+ readonly server: string;
120
+ readonly name: string;
121
+ /**
122
+ * Calls the tool. Throws `McpToolError` when the tool reports an error, and
123
+ * `McpError` when the call gets no result, or one its schema refuses.
124
+ */
125
+ call(args: A, ctx?: McpCallCtx): Promise<R>;
126
+ }
127
+ /** The connection to one MCP server, and the tools the app may call on it. */
128
+ export interface McpConnection {
129
+ readonly name: string;
130
+ /**
131
+ * Declares one of the server's tools: the only way to call it. Declared
132
+ * after `connect()`, it is checked against the server's tools at once.
133
+ */
134
+ tool<A, R>(name: string, def: McpToolDef<A, R> & {
135
+ result: Schema<R>;
136
+ }): McpTool<A, R>;
137
+ tool<A>(name: string, def: McpToolDef<A, unknown> & {
138
+ result?: undefined;
139
+ }): McpTool<A, McpResult>;
140
+ /**
141
+ * Connects, and checks every declared tool: it throws if the server has no
142
+ * tool of that name, or one that can only run as an MCP task. Call it at
143
+ * startup, so a mistake stops the app there; the first call connects
144
+ * otherwise, and fails with the same error. A server with `auth` needs
145
+ * the user to connect as, and checks the tools that user sees.
146
+ */
147
+ connect(userId?: string): Promise<void>;
148
+ /**
149
+ * For a server with `auth`: closes the user's connection, if they have
150
+ * one. Their next call makes a new one, and looks up their credential again.
151
+ */
152
+ forget(userId: string): Promise<void>;
153
+ /** Closes the connection, and stops a `stdio` server. Final: a later call fails with reason `closed`. */
154
+ close(): Promise<void>;
155
+ }
156
+ /** The connection to an MCP server. Nothing connects until `connect()` or the first call. */
157
+ export declare function mcpServer(options: McpServerOptions): McpConnection;
158
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}