@naumu/mcp 0.7.1 → 0.9.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/dist/index.js +169 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1160,21 +1160,18 @@ function registerReadThread(server2, client2) {
|
|
|
1160
1160
|
|
|
1161
1161
|
// ../mcp-core/src/tools/whoami.ts
|
|
1162
1162
|
import { z as z22 } from "zod";
|
|
1163
|
-
function registerWhoami(server2, client2
|
|
1163
|
+
function registerWhoami(server2, client2) {
|
|
1164
1164
|
server2.registerTool(
|
|
1165
1165
|
"naumu_whoami",
|
|
1166
1166
|
{
|
|
1167
1167
|
title: "Who Am I",
|
|
1168
1168
|
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
1169
|
-
description: 'Return who the calling key is
|
|
1169
|
+
description: 'Return who the calling key is, so you can bootstrap before the first real operation. A bot identity key returns its Identity row (id, graphId, name, instructions, allowedTools) plus its curated MCP tool manifest. A user API key returns `kind: "user"` with userId, name, and email - a person spans many graphs, so resolve a specific graph via naumu_list_graphs. The live tool list is already available from tools/list, so it is not repeated here. No arguments. Always available regardless of the permission grid.',
|
|
1170
1170
|
inputSchema: z22.object({})
|
|
1171
1171
|
},
|
|
1172
1172
|
async () => {
|
|
1173
1173
|
try {
|
|
1174
1174
|
const data = await client2.get("/api/identities/me/whoami");
|
|
1175
|
-
if (allToolNames && data && typeof data === "object" && data.kind === "user") {
|
|
1176
|
-
data.mcpTools = allToolNames;
|
|
1177
|
-
}
|
|
1178
1175
|
return {
|
|
1179
1176
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
1180
1177
|
};
|
|
@@ -2131,6 +2128,164 @@ function registerChatgptFetch(server2, client2) {
|
|
|
2131
2128
|
);
|
|
2132
2129
|
}
|
|
2133
2130
|
|
|
2131
|
+
// ../mcp-core/src/tools/admission-status.ts
|
|
2132
|
+
import { z as z46 } from "zod";
|
|
2133
|
+
function registerAdmissionStatus(server2, client2) {
|
|
2134
|
+
server2.registerTool(
|
|
2135
|
+
"naumu_admission_status",
|
|
2136
|
+
{
|
|
2137
|
+
title: "Admission Status",
|
|
2138
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
2139
|
+
description: "Show who can auto-join a Naumu space (graph) and who is waiting for approval: the whitelisted emails (people who join the moment they sign in with that email), the auto-join domain wildcards, and the count of pending join requests. When there are pending requests, this also returns the full list (who requested, their email, git-email hint, and message) so you can act on them with naumu_resolve_join_request. Use it during repo init to review or seed access, or whenever the user asks who has access to a space or who is asking to join.",
|
|
2140
|
+
inputSchema: z46.object({
|
|
2141
|
+
graphId: z46.string().describe("The space (graph) ID to inspect admission for. You must be a member of this space.")
|
|
2142
|
+
})
|
|
2143
|
+
},
|
|
2144
|
+
async ({ graphId }) => {
|
|
2145
|
+
try {
|
|
2146
|
+
const status = await client2.get(
|
|
2147
|
+
`/api/graphs/${graphId}/admission`
|
|
2148
|
+
);
|
|
2149
|
+
let pendingRequests;
|
|
2150
|
+
if (status && status.pendingRequestCount > 0) {
|
|
2151
|
+
pendingRequests = await client2.get(
|
|
2152
|
+
`/api/graphs/${graphId}/admission/requests?status=pending`
|
|
2153
|
+
);
|
|
2154
|
+
}
|
|
2155
|
+
const result = { ...status, pendingRequests };
|
|
2156
|
+
return {
|
|
2157
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
2158
|
+
};
|
|
2159
|
+
} catch (err) {
|
|
2160
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2161
|
+
return {
|
|
2162
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
2163
|
+
isError: true
|
|
2164
|
+
};
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
);
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
// ../mcp-core/src/tools/whitelist-members.ts
|
|
2171
|
+
import { z as z47 } from "zod";
|
|
2172
|
+
function registerWhitelistMembers(server2, client2) {
|
|
2173
|
+
server2.registerTool(
|
|
2174
|
+
"naumu_whitelist_members",
|
|
2175
|
+
{
|
|
2176
|
+
title: "Whitelist Members",
|
|
2177
|
+
annotations: {
|
|
2178
|
+
readOnlyHint: false,
|
|
2179
|
+
destructiveHint: false,
|
|
2180
|
+
idempotentHint: false,
|
|
2181
|
+
openWorldHint: false
|
|
2182
|
+
},
|
|
2183
|
+
description: "Whitelist emails so those people auto-join a Naumu space (graph) the moment they sign in with that email. Use this during repo init: after you scrub git history, present the curated list of collaborators to the user, and get their explicit confirmation, call this with the confirmed emails. It is silent - it sends no invite emails, it just pre-authorizes those addresses. Returns which entries were created and which were skipped (already whitelisted or already members). Set repoInit true when this call is part of the repo init flow.",
|
|
2184
|
+
inputSchema: z47.object({
|
|
2185
|
+
graphId: z47.string().describe("The space (graph) ID to whitelist emails for. You must be a member of this space."),
|
|
2186
|
+
emails: z47.array(z47.string()).min(1).describe("The emails to whitelist. Each becomes an exact-match auto-join entry. Present these to the user and get confirmation before calling."),
|
|
2187
|
+
repoInit: z47.boolean().optional().describe("Set true when this whitelist is being seeded as part of the repo init flow, so onboarding is tracked correctly.")
|
|
2188
|
+
})
|
|
2189
|
+
},
|
|
2190
|
+
async ({ graphId, emails, repoInit }) => {
|
|
2191
|
+
try {
|
|
2192
|
+
const result = await client2.post(`/api/graphs/${graphId}/admission/whitelist`, {
|
|
2193
|
+
entries: emails.map((email) => ({ email })),
|
|
2194
|
+
repoInit
|
|
2195
|
+
});
|
|
2196
|
+
return {
|
|
2197
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
2198
|
+
};
|
|
2199
|
+
} catch (err) {
|
|
2200
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2201
|
+
return {
|
|
2202
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
2203
|
+
isError: true
|
|
2204
|
+
};
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
);
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
// ../mcp-core/src/tools/resolve-admission.ts
|
|
2211
|
+
import { z as z48 } from "zod";
|
|
2212
|
+
function registerResolveAdmission(server2, client2) {
|
|
2213
|
+
server2.registerTool(
|
|
2214
|
+
"naumu_resolve_admission",
|
|
2215
|
+
{
|
|
2216
|
+
title: "Resolve Admission",
|
|
2217
|
+
annotations: {
|
|
2218
|
+
readOnlyHint: false,
|
|
2219
|
+
destructiveHint: false,
|
|
2220
|
+
idempotentHint: false,
|
|
2221
|
+
openWorldHint: false
|
|
2222
|
+
},
|
|
2223
|
+
description: "The call a coding agent makes right after connecting when a repo's .naumu references a space the user is not yet a member of. It evaluates whether the user can join and does it: outcome is joined-whitelist or joined-wildcard (the user is now a member - proceed), already-member (nothing to do), request-created (a join request was just filed and is awaiting a member's approval), or request-pending (a request was already open). When the response also carries reason 'seat-limit' on a request-created/request-pending outcome, the user WOULD have auto-joined via a whitelist/domain match but the space is at its seat limit - so their access is pending an admin approving them or upgrading the plan; relay that specific reason honestly, do not just say 'no match'. Pass gitEmailHint from `git config user.email` so a matching whitelist or domain rule can admit them. Relay the outcome to the user honestly: say plainly whether they joined or are waiting for approval - never imply access that is still pending.",
|
|
2224
|
+
inputSchema: z48.object({
|
|
2225
|
+
graphId: z48.string().describe("The space (graph) ID referenced by the repo .naumu file that the user wants to join."),
|
|
2226
|
+
gitEmailHint: z48.string().optional().describe("The email from `git config user.email`, used to match whitelist entries and auto-join domains.")
|
|
2227
|
+
})
|
|
2228
|
+
},
|
|
2229
|
+
async ({ graphId, gitEmailHint }) => {
|
|
2230
|
+
try {
|
|
2231
|
+
const result = await client2.post("/api/admission/resolve", {
|
|
2232
|
+
graphId,
|
|
2233
|
+
gitEmailHint
|
|
2234
|
+
});
|
|
2235
|
+
return {
|
|
2236
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
2237
|
+
};
|
|
2238
|
+
} catch (err) {
|
|
2239
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2240
|
+
return {
|
|
2241
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
2242
|
+
isError: true
|
|
2243
|
+
};
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
);
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
// ../mcp-core/src/tools/resolve-join-request.ts
|
|
2250
|
+
import { z as z49 } from "zod";
|
|
2251
|
+
function registerResolveJoinRequest(server2, client2) {
|
|
2252
|
+
server2.registerTool(
|
|
2253
|
+
"naumu_resolve_join_request",
|
|
2254
|
+
{
|
|
2255
|
+
title: "Resolve Join Request",
|
|
2256
|
+
annotations: {
|
|
2257
|
+
readOnlyHint: false,
|
|
2258
|
+
destructiveHint: false,
|
|
2259
|
+
idempotentHint: false,
|
|
2260
|
+
openWorldHint: false
|
|
2261
|
+
},
|
|
2262
|
+
description: "For a member resolving a pending join request surfaced by naumu_admission_status. Approve to add the requester to the space as a member, or deny to reject the request. Get the requestId from naumu_admission_status's pending list, and confirm the decision with the user before calling since approving grants access.",
|
|
2263
|
+
inputSchema: z49.object({
|
|
2264
|
+
graphId: z49.string().describe("The space (graph) ID the request is for. You must be a member of this space."),
|
|
2265
|
+
requestId: z49.string().describe("The pending join request ID, taken from naumu_admission_status."),
|
|
2266
|
+
action: z49.enum(["approve", "deny"]).describe("approve adds the requester as a member; deny rejects the request.")
|
|
2267
|
+
})
|
|
2268
|
+
},
|
|
2269
|
+
async ({ graphId, requestId, action }) => {
|
|
2270
|
+
try {
|
|
2271
|
+
const result = await client2.post(
|
|
2272
|
+
`/api/graphs/${graphId}/admission/requests/${requestId}/resolve`,
|
|
2273
|
+
{ action }
|
|
2274
|
+
);
|
|
2275
|
+
return {
|
|
2276
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
2277
|
+
};
|
|
2278
|
+
} catch (err) {
|
|
2279
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2280
|
+
return {
|
|
2281
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
2282
|
+
isError: true
|
|
2283
|
+
};
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
);
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2134
2289
|
// ../mcp-core/src/tools/index.ts
|
|
2135
2290
|
var TOOL_REGISTRARS = {
|
|
2136
2291
|
naumu_list_graphs: registerListGraphs,
|
|
@@ -2182,7 +2337,14 @@ var TOOL_REGISTRARS = {
|
|
|
2182
2337
|
// search + node read and emit the `{ results }` / `{ id, title, text, url }`
|
|
2183
2338
|
// shapes that client expects (see chatgpt-search.ts / chatgpt-fetch.ts).
|
|
2184
2339
|
search: registerChatgptSearch,
|
|
2185
|
-
fetch: registerChatgptFetch
|
|
2340
|
+
fetch: registerChatgptFetch,
|
|
2341
|
+
// Admission / onboarding-wedge tools (user-surface only — omitted from
|
|
2342
|
+
// BOT_ONLY_TOOL_NAMES and from the backend PERMISSION_TO_MCP_TOOLS map, so
|
|
2343
|
+
// bots never receive them, matching the naumu_list_graphs precedent).
|
|
2344
|
+
naumu_admission_status: registerAdmissionStatus,
|
|
2345
|
+
naumu_whitelist_members: registerWhitelistMembers,
|
|
2346
|
+
naumu_resolve_admission: registerResolveAdmission,
|
|
2347
|
+
naumu_resolve_join_request: registerResolveJoinRequest
|
|
2186
2348
|
};
|
|
2187
2349
|
var BOT_ONLY_TOOL_NAMES = /* @__PURE__ */ new Set(["naumu_create_thread"]);
|
|
2188
2350
|
var ALL_TOOL_NAMES = Object.keys(TOOL_REGISTRARS).filter(
|
|
@@ -2191,11 +2353,7 @@ var ALL_TOOL_NAMES = Object.keys(TOOL_REGISTRARS).filter(
|
|
|
2191
2353
|
function registerAllTools(server2, client2) {
|
|
2192
2354
|
for (const [name, registrar] of Object.entries(TOOL_REGISTRARS)) {
|
|
2193
2355
|
if (BOT_ONLY_TOOL_NAMES.has(name)) continue;
|
|
2194
|
-
|
|
2195
|
-
registerWhoami(server2, client2, ALL_TOOL_NAMES);
|
|
2196
|
-
} else {
|
|
2197
|
-
registrar(server2, client2);
|
|
2198
|
-
}
|
|
2356
|
+
registrar(server2, client2);
|
|
2199
2357
|
}
|
|
2200
2358
|
}
|
|
2201
2359
|
function registerNamedTools(server2, client2, toolNames) {
|
package/package.json
CHANGED