@opencodehub/mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -0
- package/dist/analysis-bridge.d.ts +23 -0
- package/dist/analysis-bridge.d.ts.map +1 -0
- package/dist/analysis-bridge.js +83 -0
- package/dist/analysis-bridge.js.map +1 -0
- package/dist/connection-pool.d.ts +76 -0
- package/dist/connection-pool.d.ts.map +1 -0
- package/dist/connection-pool.js +179 -0
- package/dist/connection-pool.js.map +1 -0
- package/dist/error-envelope.d.ts +97 -0
- package/dist/error-envelope.d.ts.map +1 -0
- package/dist/error-envelope.js +75 -0
- package/dist/error-envelope.js.map +1 -0
- package/dist/group-resolver.d.ts +29 -0
- package/dist/group-resolver.d.ts.map +1 -0
- package/dist/group-resolver.js +100 -0
- package/dist/group-resolver.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/next-step-hints.d.ts +24 -0
- package/dist/next-step-hints.d.ts.map +1 -0
- package/dist/next-step-hints.js +41 -0
- package/dist/next-step-hints.js.map +1 -0
- package/dist/repo-resolver.d.ts +88 -0
- package/dist/repo-resolver.d.ts.map +1 -0
- package/dist/repo-resolver.js +211 -0
- package/dist/repo-resolver.js.map +1 -0
- package/dist/repo-uri-for-entry.d.ts +25 -0
- package/dist/repo-uri-for-entry.d.ts.map +1 -0
- package/dist/repo-uri-for-entry.js +64 -0
- package/dist/repo-uri-for-entry.js.map +1 -0
- package/dist/resources/repo-cluster.d.ts +19 -0
- package/dist/resources/repo-cluster.d.ts.map +1 -0
- package/dist/resources/repo-cluster.js +203 -0
- package/dist/resources/repo-cluster.js.map +1 -0
- package/dist/resources/repo-clusters.d.ts +14 -0
- package/dist/resources/repo-clusters.d.ts.map +1 -0
- package/dist/resources/repo-clusters.js +97 -0
- package/dist/resources/repo-clusters.js.map +1 -0
- package/dist/resources/repo-context.d.ts +12 -0
- package/dist/resources/repo-context.d.ts.map +1 -0
- package/dist/resources/repo-context.js +84 -0
- package/dist/resources/repo-context.js.map +1 -0
- package/dist/resources/repo-process.d.ts +19 -0
- package/dist/resources/repo-process.d.ts.map +1 -0
- package/dist/resources/repo-process.js +220 -0
- package/dist/resources/repo-process.js.map +1 -0
- package/dist/resources/repo-processes.d.ts +13 -0
- package/dist/resources/repo-processes.d.ts.map +1 -0
- package/dist/resources/repo-processes.js +99 -0
- package/dist/resources/repo-processes.js.map +1 -0
- package/dist/resources/repo-schema.d.ts +13 -0
- package/dist/resources/repo-schema.d.ts.map +1 -0
- package/dist/resources/repo-schema.js +99 -0
- package/dist/resources/repo-schema.js.map +1 -0
- package/dist/resources/repos.d.ts +20 -0
- package/dist/resources/repos.d.ts.map +1 -0
- package/dist/resources/repos.js +58 -0
- package/dist/resources/repos.js.map +1 -0
- package/dist/resources/store-helper.d.ts +28 -0
- package/dist/resources/store-helper.d.ts.map +1 -0
- package/dist/resources/store-helper.js +58 -0
- package/dist/resources/store-helper.js.map +1 -0
- package/dist/resources/yaml.d.ts +10 -0
- package/dist/resources/yaml.d.ts.map +1 -0
- package/dist/resources/yaml.js +16 -0
- package/dist/resources/yaml.js.map +1 -0
- package/dist/server.d.ts +46 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +194 -0
- package/dist/server.js.map +1 -0
- package/dist/staleness.d.ts +19 -0
- package/dist/staleness.d.ts.map +1 -0
- package/dist/staleness.js +40 -0
- package/dist/staleness.js.map +1 -0
- package/dist/test-utils.d.ts +170 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +473 -0
- package/dist/test-utils.js.map +1 -0
- package/dist/tools/api-impact.d.ts +47 -0
- package/dist/tools/api-impact.d.ts.map +1 -0
- package/dist/tools/api-impact.js +199 -0
- package/dist/tools/api-impact.js.map +1 -0
- package/dist/tools/confidence.d.ts +39 -0
- package/dist/tools/confidence.d.ts.map +1 -0
- package/dist/tools/confidence.js +58 -0
- package/dist/tools/confidence.js.map +1 -0
- package/dist/tools/context.d.ts +47 -0
- package/dist/tools/context.d.ts.map +1 -0
- package/dist/tools/context.js +577 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/dependencies.d.ts +29 -0
- package/dist/tools/dependencies.d.ts.map +1 -0
- package/dist/tools/dependencies.js +110 -0
- package/dist/tools/dependencies.js.map +1 -0
- package/dist/tools/detect-changes.d.ts +15 -0
- package/dist/tools/detect-changes.d.ts.map +1 -0
- package/dist/tools/detect-changes.js +78 -0
- package/dist/tools/detect-changes.js.map +1 -0
- package/dist/tools/group-contracts.d.ts +26 -0
- package/dist/tools/group-contracts.d.ts.map +1 -0
- package/dist/tools/group-contracts.js +251 -0
- package/dist/tools/group-contracts.js.map +1 -0
- package/dist/tools/group-cross-repo-links.d.ts +28 -0
- package/dist/tools/group-cross-repo-links.d.ts.map +1 -0
- package/dist/tools/group-cross-repo-links.js +128 -0
- package/dist/tools/group-cross-repo-links.js.map +1 -0
- package/dist/tools/group-list.d.ts +10 -0
- package/dist/tools/group-list.d.ts.map +1 -0
- package/dist/tools/group-list.js +74 -0
- package/dist/tools/group-list.js.map +1 -0
- package/dist/tools/group-query.d.ts +40 -0
- package/dist/tools/group-query.d.ts.map +1 -0
- package/dist/tools/group-query.js +209 -0
- package/dist/tools/group-query.js.map +1 -0
- package/dist/tools/group-status.d.ts +21 -0
- package/dist/tools/group-status.d.ts.map +1 -0
- package/dist/tools/group-status.js +121 -0
- package/dist/tools/group-status.js.map +1 -0
- package/dist/tools/group-sync.d.ts +23 -0
- package/dist/tools/group-sync.d.ts.map +1 -0
- package/dist/tools/group-sync.js +112 -0
- package/dist/tools/group-sync.js.map +1 -0
- package/dist/tools/impact.d.ts +36 -0
- package/dist/tools/impact.d.ts.map +1 -0
- package/dist/tools/impact.js +232 -0
- package/dist/tools/impact.js.map +1 -0
- package/dist/tools/license-audit.d.ts +34 -0
- package/dist/tools/license-audit.d.ts.map +1 -0
- package/dist/tools/license-audit.js +108 -0
- package/dist/tools/license-audit.js.map +1 -0
- package/dist/tools/list-dead-code.d.ts +26 -0
- package/dist/tools/list-dead-code.d.ts.map +1 -0
- package/dist/tools/list-dead-code.js +110 -0
- package/dist/tools/list-dead-code.js.map +1 -0
- package/dist/tools/list-findings-delta.d.ts +36 -0
- package/dist/tools/list-findings-delta.d.ts.map +1 -0
- package/dist/tools/list-findings-delta.js +274 -0
- package/dist/tools/list-findings-delta.js.map +1 -0
- package/dist/tools/list-findings.d.ts +30 -0
- package/dist/tools/list-findings.d.ts.map +1 -0
- package/dist/tools/list-findings.js +129 -0
- package/dist/tools/list-findings.js.map +1 -0
- package/dist/tools/list-repos.d.ts +17 -0
- package/dist/tools/list-repos.d.ts.map +1 -0
- package/dist/tools/list-repos.js +63 -0
- package/dist/tools/list-repos.js.map +1 -0
- package/dist/tools/owners.d.ts +23 -0
- package/dist/tools/owners.d.ts.map +1 -0
- package/dist/tools/owners.js +103 -0
- package/dist/tools/owners.js.map +1 -0
- package/dist/tools/pack-codebase.d.ts +76 -0
- package/dist/tools/pack-codebase.d.ts.map +1 -0
- package/dist/tools/pack-codebase.js +289 -0
- package/dist/tools/pack-codebase.js.map +1 -0
- package/dist/tools/project-profile.d.ts +28 -0
- package/dist/tools/project-profile.d.ts.map +1 -0
- package/dist/tools/project-profile.js +109 -0
- package/dist/tools/project-profile.js.map +1 -0
- package/dist/tools/query.d.ts +63 -0
- package/dist/tools/query.d.ts.map +1 -0
- package/dist/tools/query.js +662 -0
- package/dist/tools/query.js.map +1 -0
- package/dist/tools/remove-dead-code.d.ts +47 -0
- package/dist/tools/remove-dead-code.d.ts.map +1 -0
- package/dist/tools/remove-dead-code.js +258 -0
- package/dist/tools/remove-dead-code.js.map +1 -0
- package/dist/tools/rename.d.ts +21 -0
- package/dist/tools/rename.d.ts.map +1 -0
- package/dist/tools/rename.js +116 -0
- package/dist/tools/rename.js.map +1 -0
- package/dist/tools/risk-trends.d.ts +19 -0
- package/dist/tools/risk-trends.d.ts.map +1 -0
- package/dist/tools/risk-trends.js +73 -0
- package/dist/tools/risk-trends.js.map +1 -0
- package/dist/tools/route-map.d.ts +27 -0
- package/dist/tools/route-map.d.ts.map +1 -0
- package/dist/tools/route-map.js +119 -0
- package/dist/tools/route-map.js.map +1 -0
- package/dist/tools/scan.d.ts +27 -0
- package/dist/tools/scan.d.ts.map +1 -0
- package/dist/tools/scan.js +136 -0
- package/dist/tools/scan.js.map +1 -0
- package/dist/tools/shape-check.d.ts +53 -0
- package/dist/tools/shape-check.d.ts.map +1 -0
- package/dist/tools/shape-check.js +161 -0
- package/dist/tools/shape-check.js.map +1 -0
- package/dist/tools/shared.d.ts +101 -0
- package/dist/tools/shared.d.ts.map +1 -0
- package/dist/tools/shared.js +114 -0
- package/dist/tools/shared.js.map +1 -0
- package/dist/tools/signature.d.ts +38 -0
- package/dist/tools/signature.d.ts.map +1 -0
- package/dist/tools/signature.js +332 -0
- package/dist/tools/signature.js.map +1 -0
- package/dist/tools/sql.d.ts +34 -0
- package/dist/tools/sql.d.ts.map +1 -0
- package/dist/tools/sql.js +222 -0
- package/dist/tools/sql.js.map +1 -0
- package/dist/tools/tool-map.d.ts +24 -0
- package/dist/tools/tool-map.d.ts.map +1 -0
- package/dist/tools/tool-map.js +97 -0
- package/dist/tools/tool-map.js.map +1 -0
- package/dist/tools/verdict.d.ts +33 -0
- package/dist/tools/verdict.d.ts.map +1 -0
- package/dist/tools/verdict.js +102 -0
- package/dist/tools/verdict.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `repoUriForEntry` — resolve a `repo_uri` for a registry entry,
|
|
3
|
+
* preferring the graph-backed `RepoNode.repoUri` when the repo's index
|
|
4
|
+
* carries one, otherwise falling back to `deriveRepoUri(entry)` from
|
|
5
|
+
* `repo-resolver.ts`.
|
|
6
|
+
*
|
|
7
|
+
* Used by the `group_*` MCP tools so that every repo-identified
|
|
8
|
+
* response row carries a stable `repo_uri` alongside its legacy `name`
|
|
9
|
+
* / `_repo` string. Lookups are best-effort — any DB-open / query
|
|
10
|
+
* failure falls back silently to the derived URI so a single unhealthy
|
|
11
|
+
* repo cannot break the whole response.
|
|
12
|
+
*
|
|
13
|
+
* Determinism: `deriveRepoUri` is pure; `RepoNode.repoUri` is byte-
|
|
14
|
+
* stable when present. Neither path depends on wall-clock.
|
|
15
|
+
*/
|
|
16
|
+
import type { ConnectionPool } from "./connection-pool.js";
|
|
17
|
+
import { type RegistryEntry } from "./repo-resolver.js";
|
|
18
|
+
/**
|
|
19
|
+
* Resolve a `repo_uri` for `entry`. Pass a `pool` when the caller already
|
|
20
|
+
* has one (every group-* tool does). Omit to fall back to the pure-derived
|
|
21
|
+
* URI without any DB access — useful for orphan rows that aren't in the
|
|
22
|
+
* registry.
|
|
23
|
+
*/
|
|
24
|
+
export declare function repoUriForEntry(entry: RegistryEntry, pool?: ConnectionPool): Promise<string>;
|
|
25
|
+
//# sourceMappingURL=repo-uri-for-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-uri-for-entry.d.ts","sourceRoot":"","sources":["../src/repo-uri-for-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAevE;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,aAAa,EACpB,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,MAAM,CAAC,CAoBjB"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `repoUriForEntry` — resolve a `repo_uri` for a registry entry,
|
|
3
|
+
* preferring the graph-backed `RepoNode.repoUri` when the repo's index
|
|
4
|
+
* carries one, otherwise falling back to `deriveRepoUri(entry)` from
|
|
5
|
+
* `repo-resolver.ts`.
|
|
6
|
+
*
|
|
7
|
+
* Used by the `group_*` MCP tools so that every repo-identified
|
|
8
|
+
* response row carries a stable `repo_uri` alongside its legacy `name`
|
|
9
|
+
* / `_repo` string. Lookups are best-effort — any DB-open / query
|
|
10
|
+
* failure falls back silently to the derived URI so a single unhealthy
|
|
11
|
+
* repo cannot break the whole response.
|
|
12
|
+
*
|
|
13
|
+
* Determinism: `deriveRepoUri` is pure; `RepoNode.repoUri` is byte-
|
|
14
|
+
* stable when present. Neither path depends on wall-clock.
|
|
15
|
+
*/
|
|
16
|
+
// biome-ignore-all lint/complexity/useLiteralKeys: dot-access disallowed on Record index signatures
|
|
17
|
+
import { resolve } from "node:path";
|
|
18
|
+
import { makeNodeId } from "@opencodehub/core-types";
|
|
19
|
+
import { resolveDbPath } from "@opencodehub/storage";
|
|
20
|
+
import { deriveRepoUri } from "./repo-resolver.js";
|
|
21
|
+
/**
|
|
22
|
+
* Preferred: read `RepoNode.repoUri` from the persisted Repo row.
|
|
23
|
+
* Only repos that were indexed with the first-class Repo entity carry
|
|
24
|
+
* this row — earlier indexes fall back to the derived URI.
|
|
25
|
+
*/
|
|
26
|
+
async function readRepoNodeUri(graph) {
|
|
27
|
+
const repoId = makeNodeId("Repo", "", "repo");
|
|
28
|
+
const repo = await graph.getRepoNode(repoId);
|
|
29
|
+
if (repo === undefined)
|
|
30
|
+
return undefined;
|
|
31
|
+
const uri = repo.repoUri;
|
|
32
|
+
return typeof uri === "string" && uri.length > 0 ? uri : undefined;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Resolve a `repo_uri` for `entry`. Pass a `pool` when the caller already
|
|
36
|
+
* has one (every group-* tool does). Omit to fall back to the pure-derived
|
|
37
|
+
* URI without any DB access — useful for orphan rows that aren't in the
|
|
38
|
+
* registry.
|
|
39
|
+
*/
|
|
40
|
+
export async function repoUriForEntry(entry, pool) {
|
|
41
|
+
if (pool !== undefined) {
|
|
42
|
+
const repoPath = resolve(entry.path);
|
|
43
|
+
const dbPath = resolveDbPath(repoPath);
|
|
44
|
+
try {
|
|
45
|
+
const store = await pool.acquire(repoPath, dbPath);
|
|
46
|
+
try {
|
|
47
|
+
const uri = await readRepoNodeUri(store.graph);
|
|
48
|
+
if (uri !== undefined)
|
|
49
|
+
return uri;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
await pool.release(repoPath);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Fall through to derived URI — a missing DB file, an unreadable
|
|
57
|
+
// nodes table, or any other transient failure must not break the
|
|
58
|
+
// group response. The repo_uri output is additive; legacy fields
|
|
59
|
+
// stay correct.
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return deriveRepoUri(entry);
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=repo-uri-for-entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-uri-for-entry.js","sourceRoot":"","sources":["../src/repo-uri-for-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,oGAAoG;AAEpG,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAsB,MAAM,oBAAoB,CAAC;AAEvE;;;;GAIG;AACH,KAAK,UAAU,eAAe,CAAC,KAAkB;IAC/C,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC;IACzB,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACrE,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAoB,EACpB,IAAqB;IAErB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACnD,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC/C,IAAI,GAAG,KAAK,SAAS;oBAAE,OAAO,GAAG,CAAC;YACpC,CAAC;oBAAS,CAAC;gBACT,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,iEAAiE;YACjE,iEAAiE;YACjE,iEAAiE;YACjE,gBAAgB;QAClB,CAAC;IACH,CAAC;IACD,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource template `codehub://repo/{name}/cluster/{clusterName}` — cluster members.
|
|
3
|
+
*
|
|
4
|
+
* Resolves `clusterName` against the Community node's `name` (stable
|
|
5
|
+
* `community-<id>` token) first, then its `inferredLabel` as a fallback
|
|
6
|
+
* so agents can pass the human-readable label. Members are joined via
|
|
7
|
+
* `MEMBER_OF` edges and ranked by `kind, name`. Cap at 100. Unknown
|
|
8
|
+
* names produce a `{error, candidates}` envelope listing up to 5
|
|
9
|
+
* similar cluster names.
|
|
10
|
+
*/
|
|
11
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
12
|
+
import type { ResourceContext } from "./repos.js";
|
|
13
|
+
export declare function registerRepoClusterResource(server: McpServer, ctx: ResourceContext): void;
|
|
14
|
+
/**
|
|
15
|
+
* Deterministic substring-first, Levenshtein-tiebreak ranker. Simple
|
|
16
|
+
* enough to be obviously correct; good enough to offer 5 neighbours.
|
|
17
|
+
*/
|
|
18
|
+
export declare function rankCandidates(needle: string, haystack: readonly string[]): readonly string[];
|
|
19
|
+
//# sourceMappingURL=repo-cluster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-cluster.d.ts","sourceRoot":"","sources":["../../src/resources/repo-cluster.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAQlD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,eAAe,GAAG,IAAI,CAiGzF;AAiDD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CAuB7F"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource template `codehub://repo/{name}/cluster/{clusterName}` — cluster members.
|
|
3
|
+
*
|
|
4
|
+
* Resolves `clusterName` against the Community node's `name` (stable
|
|
5
|
+
* `community-<id>` token) first, then its `inferredLabel` as a fallback
|
|
6
|
+
* so agents can pass the human-readable label. Members are joined via
|
|
7
|
+
* `MEMBER_OF` edges and ranked by `kind, name`. Cap at 100. Unknown
|
|
8
|
+
* names produce a `{error, candidates}` envelope listing up to 5
|
|
9
|
+
* similar cluster names.
|
|
10
|
+
*/
|
|
11
|
+
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
12
|
+
import { readRegistry } from "../repo-resolver.js";
|
|
13
|
+
import { withResourceStore } from "./store-helper.js";
|
|
14
|
+
import { yamlScalar } from "./yaml.js";
|
|
15
|
+
const PATTERN = "codehub://repo/{name}/cluster/{clusterName}";
|
|
16
|
+
const MEMBERS_CAP = 100;
|
|
17
|
+
const CANDIDATES_CAP = 5;
|
|
18
|
+
export function registerRepoClusterResource(server, ctx) {
|
|
19
|
+
const template = new ResourceTemplate(PATTERN, {
|
|
20
|
+
list: async () => {
|
|
21
|
+
const opts = ctx.home !== undefined ? { home: ctx.home } : {};
|
|
22
|
+
const reg = await readRegistry(opts);
|
|
23
|
+
return {
|
|
24
|
+
resources: Object.keys(reg)
|
|
25
|
+
.sort()
|
|
26
|
+
.map((name) => ({
|
|
27
|
+
name: `${name}/cluster/{clusterName}`,
|
|
28
|
+
uri: `codehub://repo/${encodeURIComponent(name)}/cluster/{clusterName}`,
|
|
29
|
+
mimeType: "text/yaml",
|
|
30
|
+
description: `Members of a community cluster in repo ${name}`,
|
|
31
|
+
})),
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
server.registerResource("repo-cluster", template, {
|
|
36
|
+
title: "Repo cluster members",
|
|
37
|
+
description: "YAML list of symbols that MEMBER_OF a named community cluster. Cap 100. Ranked by kind, name.",
|
|
38
|
+
mimeType: "text/yaml",
|
|
39
|
+
}, async (uri, variables) => {
|
|
40
|
+
const nameRaw = variables["name"];
|
|
41
|
+
const clusterRaw = variables["clusterName"];
|
|
42
|
+
const nameVar = Array.isArray(nameRaw) ? nameRaw[0] : nameRaw;
|
|
43
|
+
const clusterVar = Array.isArray(clusterRaw) ? clusterRaw[0] : clusterRaw;
|
|
44
|
+
const repoName = nameVar ? decodeURIComponent(String(nameVar)) : undefined;
|
|
45
|
+
const clusterName = clusterVar ? decodeURIComponent(String(clusterVar)) : "";
|
|
46
|
+
const resourceOpts = {};
|
|
47
|
+
if (ctx.home !== undefined)
|
|
48
|
+
resourceOpts.home = ctx.home;
|
|
49
|
+
if (ctx.pool !== undefined)
|
|
50
|
+
resourceOpts.pool = ctx.pool;
|
|
51
|
+
return withResourceStore(uri.href, repoName, resourceOpts, async (store, resolvedRepo) => {
|
|
52
|
+
const graph = store.graph;
|
|
53
|
+
const communities = (await graph.listNodesByKind("Community"));
|
|
54
|
+
const hit = communities.find((c) => c.name === clusterName || c.inferredLabel === clusterName);
|
|
55
|
+
if (hit === undefined) {
|
|
56
|
+
return buildNotFound(uri.href, resolvedRepo, clusterName, communities);
|
|
57
|
+
}
|
|
58
|
+
const communityId = hit.id;
|
|
59
|
+
const communityLabel = typeof hit.inferredLabel === "string" && hit.inferredLabel.length > 0
|
|
60
|
+
? hit.inferredLabel
|
|
61
|
+
: null;
|
|
62
|
+
const communityName = hit.name;
|
|
63
|
+
const memberEdges = await graph.listEdgesByType("MEMBER_OF", { toIds: [communityId] });
|
|
64
|
+
const memberIds = Array.from(new Set(memberEdges.map((e) => e.from)));
|
|
65
|
+
const members = memberIds.length > 0 ? [...(await graph.listNodes({ ids: memberIds }))] : [];
|
|
66
|
+
members.sort((a, b) => {
|
|
67
|
+
if (a.kind !== b.kind)
|
|
68
|
+
return a.kind < b.kind ? -1 : 1;
|
|
69
|
+
if (a.name !== b.name)
|
|
70
|
+
return a.name < b.name ? -1 : 1;
|
|
71
|
+
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
72
|
+
});
|
|
73
|
+
const cappedMembers = members.slice(0, MEMBERS_CAP);
|
|
74
|
+
const lines = [];
|
|
75
|
+
lines.push(`repo: ${yamlScalar(resolvedRepo)}`);
|
|
76
|
+
lines.push(`cluster:`);
|
|
77
|
+
lines.push(` id: ${yamlScalar(communityId)}`);
|
|
78
|
+
lines.push(` name: ${yamlScalar(communityName)}`);
|
|
79
|
+
if (communityLabel) {
|
|
80
|
+
lines.push(` label: ${yamlScalar(communityLabel)}`);
|
|
81
|
+
}
|
|
82
|
+
lines.push("members:");
|
|
83
|
+
if (cappedMembers.length === 0) {
|
|
84
|
+
lines.push(" []");
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
for (const m of cappedMembers) {
|
|
88
|
+
lines.push(` - id: ${yamlScalar(m.id)}`);
|
|
89
|
+
lines.push(` name: ${yamlScalar(m.name)}`);
|
|
90
|
+
lines.push(` kind: ${yamlScalar(m.kind)}`);
|
|
91
|
+
lines.push(` filePath: ${yamlScalar(m.filePath)}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
contents: [
|
|
96
|
+
{
|
|
97
|
+
uri: uri.href,
|
|
98
|
+
mimeType: "text/yaml",
|
|
99
|
+
text: `${lines.join("\n")}\n`,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
async function buildNotFound(uri, repoName, clusterName, communities) {
|
|
107
|
+
const ordered = [...communities].sort((a, b) => {
|
|
108
|
+
const ac = a.symbolCount ?? 0;
|
|
109
|
+
const bc = b.symbolCount ?? 0;
|
|
110
|
+
if (ac !== bc)
|
|
111
|
+
return bc - ac;
|
|
112
|
+
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
113
|
+
});
|
|
114
|
+
const candidates = rankCandidates(clusterName, ordered.flatMap((c) => {
|
|
115
|
+
const out = [];
|
|
116
|
+
const n = typeof c.name === "string" ? c.name : null;
|
|
117
|
+
const l = typeof c.inferredLabel === "string" ? c.inferredLabel : null;
|
|
118
|
+
if (n)
|
|
119
|
+
out.push(n);
|
|
120
|
+
if (l && l !== n)
|
|
121
|
+
out.push(l);
|
|
122
|
+
return out;
|
|
123
|
+
})).slice(0, CANDIDATES_CAP);
|
|
124
|
+
const lines = [];
|
|
125
|
+
lines.push(`repo: ${yamlScalar(repoName)}`);
|
|
126
|
+
lines.push(`cluster: ${yamlScalar(clusterName)}`);
|
|
127
|
+
lines.push('error: "not found"');
|
|
128
|
+
lines.push("candidates:");
|
|
129
|
+
if (candidates.length === 0) {
|
|
130
|
+
lines.push(" []");
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
for (const c of candidates) {
|
|
134
|
+
lines.push(` - ${yamlScalar(c)}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
contents: [
|
|
139
|
+
{
|
|
140
|
+
uri,
|
|
141
|
+
mimeType: "text/yaml",
|
|
142
|
+
text: `${lines.join("\n")}\n`,
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Deterministic substring-first, Levenshtein-tiebreak ranker. Simple
|
|
149
|
+
* enough to be obviously correct; good enough to offer 5 neighbours.
|
|
150
|
+
*/
|
|
151
|
+
export function rankCandidates(needle, haystack) {
|
|
152
|
+
const lower = needle.toLowerCase();
|
|
153
|
+
const scored = haystack.map((h) => {
|
|
154
|
+
const lh = h.toLowerCase();
|
|
155
|
+
let score = 0;
|
|
156
|
+
if (lh === lower)
|
|
157
|
+
score = 1000;
|
|
158
|
+
else if (lh.startsWith(lower))
|
|
159
|
+
score = 500 - Math.abs(lh.length - lower.length);
|
|
160
|
+
else if (lh.includes(lower))
|
|
161
|
+
score = 250 - Math.abs(lh.length - lower.length);
|
|
162
|
+
else
|
|
163
|
+
score = 100 - levenshtein(lh, lower);
|
|
164
|
+
return { value: h, score };
|
|
165
|
+
});
|
|
166
|
+
scored.sort((a, b) => {
|
|
167
|
+
if (b.score !== a.score)
|
|
168
|
+
return b.score - a.score;
|
|
169
|
+
return a.value < b.value ? -1 : a.value > b.value ? 1 : 0;
|
|
170
|
+
});
|
|
171
|
+
const seen = new Set();
|
|
172
|
+
const out = [];
|
|
173
|
+
for (const s of scored) {
|
|
174
|
+
if (seen.has(s.value))
|
|
175
|
+
continue;
|
|
176
|
+
seen.add(s.value);
|
|
177
|
+
out.push(s.value);
|
|
178
|
+
}
|
|
179
|
+
return out;
|
|
180
|
+
}
|
|
181
|
+
function levenshtein(a, b) {
|
|
182
|
+
if (a === b)
|
|
183
|
+
return 0;
|
|
184
|
+
if (a.length === 0)
|
|
185
|
+
return b.length;
|
|
186
|
+
if (b.length === 0)
|
|
187
|
+
return a.length;
|
|
188
|
+
const prev = new Array(b.length + 1);
|
|
189
|
+
const cur = new Array(b.length + 1);
|
|
190
|
+
for (let j = 0; j <= b.length; j += 1)
|
|
191
|
+
prev[j] = j;
|
|
192
|
+
for (let i = 1; i <= a.length; i += 1) {
|
|
193
|
+
cur[0] = i;
|
|
194
|
+
for (let j = 1; j <= b.length; j += 1) {
|
|
195
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
196
|
+
cur[j] = Math.min((cur[j - 1] ?? 0) + 1, (prev[j] ?? 0) + 1, (prev[j - 1] ?? 0) + cost);
|
|
197
|
+
}
|
|
198
|
+
for (let j = 0; j <= b.length; j += 1)
|
|
199
|
+
prev[j] = cur[j] ?? 0;
|
|
200
|
+
}
|
|
201
|
+
return prev[b.length] ?? 0;
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=repo-cluster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-cluster.js","sourceRoot":"","sources":["../../src/resources/repo-cluster.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource template `codehub://repo/{name}/clusters` — list community clusters.
|
|
3
|
+
*
|
|
4
|
+
* Each row corresponds to a `Community` node emitted by the communities
|
|
5
|
+
* phase (Leiden over the CALLS + HAS_METHOD callable graph). The agent
|
|
6
|
+
* uses this as the entry point for behavioural navigation: pick a
|
|
7
|
+
* cluster, then read `codehub://repo/{name}/cluster/{clusterName}` for
|
|
8
|
+
* its members. Ranked by `symbolCount DESC, cohesion DESC` so the
|
|
9
|
+
* highest-impact clusters surface first; capped at 20.
|
|
10
|
+
*/
|
|
11
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
12
|
+
import type { ResourceContext } from "./repos.js";
|
|
13
|
+
export declare function registerRepoClustersResource(server: McpServer, ctx: ResourceContext): void;
|
|
14
|
+
//# sourceMappingURL=repo-clusters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-clusters.d.ts","sourceRoot":"","sources":["../../src/resources/repo-clusters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAOlD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,eAAe,GAAG,IAAI,CAmF1F"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource template `codehub://repo/{name}/clusters` — list community clusters.
|
|
3
|
+
*
|
|
4
|
+
* Each row corresponds to a `Community` node emitted by the communities
|
|
5
|
+
* phase (Leiden over the CALLS + HAS_METHOD callable graph). The agent
|
|
6
|
+
* uses this as the entry point for behavioural navigation: pick a
|
|
7
|
+
* cluster, then read `codehub://repo/{name}/cluster/{clusterName}` for
|
|
8
|
+
* its members. Ranked by `symbolCount DESC, cohesion DESC` so the
|
|
9
|
+
* highest-impact clusters surface first; capped at 20.
|
|
10
|
+
*/
|
|
11
|
+
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
12
|
+
import { readRegistry } from "../repo-resolver.js";
|
|
13
|
+
import { withResourceStore } from "./store-helper.js";
|
|
14
|
+
import { yamlScalar } from "./yaml.js";
|
|
15
|
+
const PATTERN = "codehub://repo/{name}/clusters";
|
|
16
|
+
const RESULT_CAP = 20;
|
|
17
|
+
export function registerRepoClustersResource(server, ctx) {
|
|
18
|
+
const template = new ResourceTemplate(PATTERN, {
|
|
19
|
+
list: async () => {
|
|
20
|
+
const opts = ctx.home !== undefined ? { home: ctx.home } : {};
|
|
21
|
+
const reg = await readRegistry(opts);
|
|
22
|
+
return {
|
|
23
|
+
resources: Object.keys(reg)
|
|
24
|
+
.sort()
|
|
25
|
+
.map((name) => ({
|
|
26
|
+
name: `${name}/clusters`,
|
|
27
|
+
uri: `codehub://repo/${encodeURIComponent(name)}/clusters`,
|
|
28
|
+
mimeType: "text/yaml",
|
|
29
|
+
description: `Community clusters for repo ${name}`,
|
|
30
|
+
})),
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
server.registerResource("repo-clusters", template, {
|
|
35
|
+
title: "Repo clusters",
|
|
36
|
+
description: "YAML list of Community nodes (Leiden clusters) ranked by size and cohesion. Cap 20.",
|
|
37
|
+
mimeType: "text/yaml",
|
|
38
|
+
}, async (uri, variables) => {
|
|
39
|
+
const raw = variables["name"];
|
|
40
|
+
const nameVar = Array.isArray(raw) ? raw[0] : raw;
|
|
41
|
+
const decoded = nameVar ? decodeURIComponent(String(nameVar)) : undefined;
|
|
42
|
+
const resourceOpts = {};
|
|
43
|
+
if (ctx.home !== undefined)
|
|
44
|
+
resourceOpts.home = ctx.home;
|
|
45
|
+
if (ctx.pool !== undefined)
|
|
46
|
+
resourceOpts.pool = ctx.pool;
|
|
47
|
+
return withResourceStore(uri.href, decoded, resourceOpts, async (store, repoName) => {
|
|
48
|
+
const communities = (await store.graph.listNodesByKind("Community"));
|
|
49
|
+
const rows = [...communities]
|
|
50
|
+
.sort((a, b) => {
|
|
51
|
+
const ac = a.symbolCount ?? 0;
|
|
52
|
+
const bc = b.symbolCount ?? 0;
|
|
53
|
+
if (ac !== bc)
|
|
54
|
+
return bc - ac;
|
|
55
|
+
const ah = a.cohesion ?? 0;
|
|
56
|
+
const bh = b.cohesion ?? 0;
|
|
57
|
+
if (ah !== bh)
|
|
58
|
+
return bh - ah;
|
|
59
|
+
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
60
|
+
})
|
|
61
|
+
.slice(0, RESULT_CAP);
|
|
62
|
+
const lines = [];
|
|
63
|
+
lines.push(`repo: ${yamlScalar(repoName)}`);
|
|
64
|
+
lines.push("clusters:");
|
|
65
|
+
if (rows.length === 0) {
|
|
66
|
+
lines.push(" []");
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
for (const c of rows) {
|
|
70
|
+
lines.push(` - id: ${yamlScalar(c.id)}`);
|
|
71
|
+
lines.push(` name: ${yamlScalar(c.name)}`);
|
|
72
|
+
if (c.inferredLabel && c.inferredLabel.length > 0) {
|
|
73
|
+
lines.push(` label: ${yamlScalar(c.inferredLabel)}`);
|
|
74
|
+
}
|
|
75
|
+
lines.push(` symbolCount: ${c.symbolCount ?? 0}`);
|
|
76
|
+
lines.push(` cohesion: ${c.cohesion ?? 0}`);
|
|
77
|
+
if (c.keywords && c.keywords.length > 0) {
|
|
78
|
+
lines.push(" keywords:");
|
|
79
|
+
for (const kw of c.keywords) {
|
|
80
|
+
lines.push(` - ${yamlScalar(kw)}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
contents: [
|
|
87
|
+
{
|
|
88
|
+
uri: uri.href,
|
|
89
|
+
mimeType: "text/yaml",
|
|
90
|
+
text: `${lines.join("\n")}\n`,
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=repo-clusters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-clusters.js","sourceRoot":"","sources":["../../src/resources/repo-clusters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource template `codehub://repo/{name}/context` — per-repo overview.
|
|
3
|
+
*
|
|
4
|
+
* Emits stats + staleness + a curated list of available tools so agents
|
|
5
|
+
* learn what they can do in a single `resources/read`. The `list`
|
|
6
|
+
* callback enumerates the same URI pattern for every registered repo so
|
|
7
|
+
* clients like Claude Code show them in the @-mention picker.
|
|
8
|
+
*/
|
|
9
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10
|
+
import type { ResourceContext } from "./repos.js";
|
|
11
|
+
export declare function registerRepoContextResource(server: McpServer, ctx: ResourceContext): void;
|
|
12
|
+
//# sourceMappingURL=repo-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-context.d.ts","sourceRoot":"","sources":["../../src/resources/repo-context.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAclD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,eAAe,GAAG,IAAI,CAmEzF"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource template `codehub://repo/{name}/context` — per-repo overview.
|
|
3
|
+
*
|
|
4
|
+
* Emits stats + staleness + a curated list of available tools so agents
|
|
5
|
+
* learn what they can do in a single `resources/read`. The `list`
|
|
6
|
+
* callback enumerates the same URI pattern for every registered repo so
|
|
7
|
+
* clients like Claude Code show them in the @-mention picker.
|
|
8
|
+
*/
|
|
9
|
+
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10
|
+
import { resolveRepo } from "../repo-resolver.js";
|
|
11
|
+
import { stalenessFromMeta } from "../staleness.js";
|
|
12
|
+
const PATTERN = "codehub://repo/{name}/context";
|
|
13
|
+
const AVAILABLE_TOOLS = [
|
|
14
|
+
"list_repos",
|
|
15
|
+
"query",
|
|
16
|
+
"context",
|
|
17
|
+
"impact",
|
|
18
|
+
"detect_changes",
|
|
19
|
+
"rename",
|
|
20
|
+
"sql",
|
|
21
|
+
];
|
|
22
|
+
export function registerRepoContextResource(server, ctx) {
|
|
23
|
+
const template = new ResourceTemplate(PATTERN, {
|
|
24
|
+
list: async () => {
|
|
25
|
+
const { readRegistry } = await import("../repo-resolver.js");
|
|
26
|
+
const opts = ctx.home !== undefined ? { home: ctx.home } : {};
|
|
27
|
+
const reg = await readRegistry(opts);
|
|
28
|
+
return {
|
|
29
|
+
resources: Object.keys(reg)
|
|
30
|
+
.sort()
|
|
31
|
+
.map((name) => ({
|
|
32
|
+
name: `${name}/context`,
|
|
33
|
+
uri: `codehub://repo/${encodeURIComponent(name)}/context`,
|
|
34
|
+
mimeType: "text/yaml",
|
|
35
|
+
description: `Context card for repo ${name}`,
|
|
36
|
+
})),
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
server.registerResource("repo-context", template, {
|
|
41
|
+
title: "Repo context card",
|
|
42
|
+
description: "YAML overview of a registered repo: stats, staleness, and the tools available to act on it.",
|
|
43
|
+
mimeType: "text/yaml",
|
|
44
|
+
}, async (uri, variables) => {
|
|
45
|
+
const raw = variables["name"];
|
|
46
|
+
const nameVar = Array.isArray(raw) ? raw[0] : raw;
|
|
47
|
+
const decoded = nameVar ? decodeURIComponent(String(nameVar)) : undefined;
|
|
48
|
+
const opts = ctx.home !== undefined ? { home: ctx.home } : {};
|
|
49
|
+
const resolved = await resolveRepo(decoded, opts);
|
|
50
|
+
const staleness = stalenessFromMeta(resolved.meta);
|
|
51
|
+
const lines = [];
|
|
52
|
+
lines.push(`repo: ${resolved.name}`);
|
|
53
|
+
lines.push(`path: ${resolved.repoPath}`);
|
|
54
|
+
lines.push("stats:");
|
|
55
|
+
lines.push(` nodeCount: ${resolved.entry.nodeCount}`);
|
|
56
|
+
lines.push(` edgeCount: ${resolved.entry.edgeCount}`);
|
|
57
|
+
lines.push(` indexedAt: ${resolved.entry.indexedAt}`);
|
|
58
|
+
if (resolved.entry.lastCommit) {
|
|
59
|
+
lines.push(` lastCommit: ${resolved.entry.lastCommit}`);
|
|
60
|
+
}
|
|
61
|
+
if (staleness) {
|
|
62
|
+
lines.push("staleness:");
|
|
63
|
+
lines.push(` isStale: ${staleness.isStale}`);
|
|
64
|
+
lines.push(` commitsBehind: ${staleness.commitsBehind}`);
|
|
65
|
+
if (staleness.lastIndexedCommit) {
|
|
66
|
+
lines.push(` lastIndexedCommit: ${staleness.lastIndexedCommit}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
lines.push("available_tools:");
|
|
70
|
+
for (const t of AVAILABLE_TOOLS) {
|
|
71
|
+
lines.push(` - ${t}`);
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
contents: [
|
|
75
|
+
{
|
|
76
|
+
uri: uri.href,
|
|
77
|
+
mimeType: "text/yaml",
|
|
78
|
+
text: `${lines.join("\n")}\n`,
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=repo-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-context.js","sourceRoot":"","sources":["../../src/resources/repo-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource template `codehub://repo/{name}/process/{processName}` — process trace.
|
|
3
|
+
*
|
|
4
|
+
* Resolves `processName` against the Process node's `name` first (the
|
|
5
|
+
* synthesised `<entry>-flow` token), then its `inferredLabel` as a
|
|
6
|
+
* fallback. The ordered trace walks PROCESS_STEP edges starting from
|
|
7
|
+
* the entry point (step 0) through every BFS-reached symbol. Unknown
|
|
8
|
+
* names produce a `{error, candidates}` envelope listing up to 5 close
|
|
9
|
+
* matches.
|
|
10
|
+
*
|
|
11
|
+
* PROCESS_STEP edges live between callable symbols (not between the
|
|
12
|
+
* Process node and its members). The entry point itself is the
|
|
13
|
+
* `from_id` of the first step emitted by the phase; we surface it as
|
|
14
|
+
* step 0 with its own row so the trace is usable standalone.
|
|
15
|
+
*/
|
|
16
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
17
|
+
import type { ResourceContext } from "./repos.js";
|
|
18
|
+
export declare function registerRepoProcessResource(server: McpServer, ctx: ResourceContext): void;
|
|
19
|
+
//# sourceMappingURL=repo-process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-process.d.ts","sourceRoot":"","sources":["../../src/resources/repo-process.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAOlD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,eAAe,GAAG,IAAI,CAqGzF"}
|