devmap 0.4.2__tar.gz → 0.4.3__tar.gz
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.
- {devmap-0.4.2 → devmap-0.4.3}/PKG-INFO +2 -2
- {devmap-0.4.2 → devmap-0.4.3}/README.md +1 -1
- {devmap-0.4.2 → devmap-0.4.3}/devmap/_devmap.mjs +286 -115
- {devmap-0.4.2 → devmap-0.4.3}/devmap.egg-info/PKG-INFO +2 -2
- {devmap-0.4.2 → devmap-0.4.3}/pyproject.toml +1 -1
- {devmap-0.4.2 → devmap-0.4.3}/devmap/__init__.py +0 -0
- {devmap-0.4.2 → devmap-0.4.3}/devmap.egg-info/SOURCES.txt +0 -0
- {devmap-0.4.2 → devmap-0.4.3}/devmap.egg-info/dependency_links.txt +0 -0
- {devmap-0.4.2 → devmap-0.4.3}/devmap.egg-info/entry_points.txt +0 -0
- {devmap-0.4.2 → devmap-0.4.3}/devmap.egg-info/top_level.txt +0 -0
- {devmap-0.4.2 → devmap-0.4.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devmap
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Map your machine's dev environment and surface issues (PATH conflicts, ghost binaries, multi-version collisions). fastfetch-for-dev-tools. This PyPI package ships the real devmap CLI (a bundled JavaScript app launched via Node.js or Bun), so `pip install devmap && devmap` works standalone.
|
|
5
5
|
Author: devmap contributors
|
|
6
6
|
License: MIT
|
|
@@ -109,7 +109,7 @@ Register it with any MCP-capable agent (Cursor / Cline / Claude Desktop / Codex
|
|
|
109
109
|
}
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
Three tools are exposed
|
|
112
|
+
Three tools are exposed. The server targets **MCP `2026-07-28`** — stateless core (`server/discover`, no handshake required), tool `annotations` (`readOnlyHint`), JSON Schema `outputSchema` + `structuredContent` results, and cacheable `tools/list` — while still answering the legacy `initialize` handshake for older clients.
|
|
113
113
|
|
|
114
114
|
| Tool | Purpose |
|
|
115
115
|
|------|---------|
|
|
@@ -91,7 +91,7 @@ Register it with any MCP-capable agent (Cursor / Cline / Claude Desktop / Codex
|
|
|
91
91
|
}
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
Three tools are exposed
|
|
94
|
+
Three tools are exposed. The server targets **MCP `2026-07-28`** — stateless core (`server/discover`, no handshake required), tool `annotations` (`readOnlyHint`), JSON Schema `outputSchema` + `structuredContent` results, and cacheable `tools/list` — while still answering the legacy `initialize` handshake for older clients.
|
|
95
95
|
|
|
96
96
|
| Tool | Purpose |
|
|
97
97
|
|------|---------|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/version.ts
|
|
5
|
-
var VERSION = "0.4.
|
|
5
|
+
var VERSION = "0.4.3";
|
|
6
6
|
|
|
7
7
|
// src/install.ts
|
|
8
8
|
function isIsolated(i) {
|
|
@@ -1386,65 +1386,141 @@ function queryManifest(m, opts) {
|
|
|
1386
1386
|
}
|
|
1387
1387
|
|
|
1388
1388
|
// src/mcp.ts
|
|
1389
|
-
var
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
}
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1389
|
+
var SUPPORTED_PROTOCOLS = [
|
|
1390
|
+
"2024-11-05",
|
|
1391
|
+
"2025-03-26",
|
|
1392
|
+
"2025-06-18",
|
|
1393
|
+
"2025-11-25",
|
|
1394
|
+
"2026-07-28"
|
|
1395
|
+
];
|
|
1396
|
+
var PREFERRED_PROTOCOL = "2026-07-28";
|
|
1397
|
+
var TOOLS_TTL_MS = 300000;
|
|
1398
|
+
var TOOLS_CACHE_SCOPE = "public";
|
|
1399
|
+
var SERVER_INFO = { name: "devmap", version: VERSION };
|
|
1400
|
+
var CHECK_SCHEMA = {
|
|
1401
|
+
type: "object",
|
|
1402
|
+
description: "One finding: a missing tool, a PATH conflict, a ghost binary, a health or security issue.",
|
|
1403
|
+
required: ["ID", "Kind", "Severity", "Label", "Detail"],
|
|
1404
|
+
properties: {
|
|
1405
|
+
ID: { type: "string", description: "Stable rule id; pass a prefix to --disable to silence it." },
|
|
1406
|
+
Kind: {
|
|
1407
|
+
type: "string",
|
|
1408
|
+
enum: ["missing", "conflict", "ghost", "mismatch", "stale", "vuln", "secret"]
|
|
1409
|
+
},
|
|
1410
|
+
Severity: { type: "string", enum: ["ok", "info", "warn", "error", "missing"] },
|
|
1411
|
+
Label: { type: "string" },
|
|
1412
|
+
Detail: { type: "string" },
|
|
1413
|
+
Path: { type: "array", items: { type: "string" } }
|
|
1414
|
+
},
|
|
1415
|
+
additionalProperties: true
|
|
1416
|
+
};
|
|
1417
|
+
var MANIFEST_SCHEMA = {
|
|
1418
|
+
type: "object",
|
|
1419
|
+
description: "The full devmap manifest (schema devmap.manifest/1.0).",
|
|
1420
|
+
required: ["meta", "summary", "checks"],
|
|
1421
|
+
properties: {
|
|
1422
|
+
meta: {
|
|
1423
|
+
type: "object",
|
|
1424
|
+
required: ["tool", "version", "generatedAt", "schema"],
|
|
1425
|
+
properties: {
|
|
1426
|
+
tool: { type: "string", const: "devmap" },
|
|
1427
|
+
version: { type: "string" },
|
|
1428
|
+
generatedAt: { type: "string", format: "date-time" },
|
|
1429
|
+
schema: { type: "string" },
|
|
1430
|
+
shells: { type: "array", items: { type: "string" } }
|
|
1431
|
+
},
|
|
1432
|
+
additionalProperties: true
|
|
1433
|
+
},
|
|
1434
|
+
summary: {
|
|
1435
|
+
type: "object",
|
|
1436
|
+
description: "Aggregates: tool/installation counts, multi-version tools, issueCountBySeverity, per-layer environment sizes.",
|
|
1437
|
+
additionalProperties: true
|
|
1438
|
+
},
|
|
1439
|
+
checks: { type: "array", items: CHECK_SCHEMA },
|
|
1440
|
+
conflicts: {
|
|
1441
|
+
type: "object",
|
|
1442
|
+
description: "The PATH conflict graph: multi-version groups, shadowed binaries, broken symlinks.",
|
|
1443
|
+
additionalProperties: true
|
|
1444
|
+
},
|
|
1445
|
+
runtimes: { type: "array", items: { type: "object", additionalProperties: true } },
|
|
1446
|
+
packageManagers: { type: "array", items: { type: "object", additionalProperties: true } },
|
|
1447
|
+
ides: { type: "array", items: { type: "object", additionalProperties: true } },
|
|
1448
|
+
environments: { type: "object", additionalProperties: true },
|
|
1449
|
+
sdks: { type: "object", description: "Android / Flutter / Dart / NDK state.", additionalProperties: true },
|
|
1450
|
+
windows: { type: "object", description: "Windows pre-flight state.", additionalProperties: true },
|
|
1451
|
+
system: { type: "object", additionalProperties: true }
|
|
1452
|
+
},
|
|
1453
|
+
additionalProperties: true
|
|
1454
|
+
};
|
|
1455
|
+
var QUERY_SCHEMA = {
|
|
1456
|
+
type: "object",
|
|
1457
|
+
description: "A filtered view of a scan: matching tool groups, related checks, and optional conflicts.",
|
|
1458
|
+
required: ["groups", "checks"],
|
|
1459
|
+
properties: {
|
|
1460
|
+
groups: {
|
|
1461
|
+
type: "array",
|
|
1462
|
+
items: {
|
|
1463
|
+
type: "object",
|
|
1464
|
+
required: ["id", "category", "installs"],
|
|
1465
|
+
properties: {
|
|
1466
|
+
id: { type: "string" },
|
|
1467
|
+
category: { type: "string", enum: ["runtime", "packageManager", "ide"] },
|
|
1468
|
+
installs: { type: "array", items: { type: "object", additionalProperties: true } }
|
|
1469
|
+
},
|
|
1470
|
+
additionalProperties: true
|
|
1471
|
+
}
|
|
1472
|
+
},
|
|
1473
|
+
checks: { type: "array", items: CHECK_SCHEMA },
|
|
1474
|
+
conflicts: { type: "object", additionalProperties: true }
|
|
1475
|
+
},
|
|
1476
|
+
additionalProperties: true
|
|
1477
|
+
};
|
|
1478
|
+
var PREFLIGHT_SCHEMA = {
|
|
1479
|
+
type: "object",
|
|
1480
|
+
description: "The pre-flight verdict: can this machine run the intended command cleanly right now?",
|
|
1481
|
+
required: ["ok", "blockers", "warnings"],
|
|
1482
|
+
properties: {
|
|
1483
|
+
ok: { type: "boolean", description: "True when `blockers` is empty — the agent may proceed." },
|
|
1484
|
+
blockers: {
|
|
1485
|
+
type: "array",
|
|
1486
|
+
items: { type: "string" },
|
|
1487
|
+
description: "Rule ids at error severity. Non-empty ⇒ fix these before running anything."
|
|
1488
|
+
},
|
|
1489
|
+
warnings: { type: "array", items: { type: "string" }, description: "Rule ids at warn severity." },
|
|
1490
|
+
executionPolicy: { type: ["string", "null"], description: "PowerShell execution policy, if applicable." },
|
|
1491
|
+
languageMode: {
|
|
1492
|
+
type: ["string", "null"],
|
|
1493
|
+
description: "PowerShell language mode (ConstrainedLanguage blocks agents)."
|
|
1494
|
+
},
|
|
1495
|
+
codepage: { type: ["integer", "null"], description: "Active console code page (936 = GBK)." },
|
|
1496
|
+
schannelRevoke: { type: ["boolean", "null"], description: "Whether schannel does cert-revocation checks." },
|
|
1431
1497
|
windows: {
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1498
|
+
type: "object",
|
|
1499
|
+
properties: {
|
|
1500
|
+
present: { type: "boolean" },
|
|
1501
|
+
appAliases: { type: "integer", description: "App Execution Aliases that can shadow a real binary." },
|
|
1502
|
+
safeDelete: { type: "boolean", description: "Whether a safe-delete shim makes deletions fail closed." }
|
|
1503
|
+
},
|
|
1504
|
+
additionalProperties: true
|
|
1435
1505
|
},
|
|
1436
1506
|
sdk: {
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1507
|
+
type: "object",
|
|
1508
|
+
description: "Android / Flutter / Dart state, or null when the toolchain is absent.",
|
|
1509
|
+
additionalProperties: true
|
|
1440
1510
|
},
|
|
1441
|
-
pathConflicts:
|
|
1442
|
-
|
|
1443
|
-
|
|
1511
|
+
pathConflicts: {
|
|
1512
|
+
type: "integer",
|
|
1513
|
+
description: "Number of PATH conflicts that could change which binary runs."
|
|
1514
|
+
}
|
|
1515
|
+
},
|
|
1516
|
+
additionalProperties: true
|
|
1517
|
+
};
|
|
1518
|
+
var READ_ONLY = { readOnlyHint: true, destructiveHint: false, idempotentHint: true };
|
|
1444
1519
|
var TOOLS = [
|
|
1445
1520
|
{
|
|
1446
1521
|
name: "scan_environment",
|
|
1447
1522
|
description: "Run a full devmap scan of the local development environment and return the structured manifest " + "(detected tools across runtimes/pkg-managers/IDEs, PATH conflicts & ghost binaries, per-env health " + "checks, and the security posture). Use this first to understand a machine before proposing changes.",
|
|
1523
|
+
annotations: { ...READ_ONLY, openWorldHint: true },
|
|
1448
1524
|
inputSchema: {
|
|
1449
1525
|
type: "object",
|
|
1450
1526
|
properties: {
|
|
@@ -1469,11 +1545,13 @@ var TOOLS = [
|
|
|
1469
1545
|
description: "Opt-in: scan a curated allowlist of HOME/project credential files for hardcoded secrets (offline)."
|
|
1470
1546
|
}
|
|
1471
1547
|
}
|
|
1472
|
-
}
|
|
1548
|
+
},
|
|
1549
|
+
outputSchema: MANIFEST_SCHEMA
|
|
1473
1550
|
},
|
|
1474
1551
|
{
|
|
1475
1552
|
name: "query_tool",
|
|
1476
1553
|
description: "Query a scan for a specific tool, semantic category, conflict, or issue — e.g. selector 'node', " + "'runtime.node', 'pkg.npm', 'git', or 'python'. Returns matching installs plus any related findings. " + "Cheaper than a full scan when you already know what you are looking for.",
|
|
1554
|
+
annotations: { ...READ_ONLY, openWorldHint: false },
|
|
1477
1555
|
inputSchema: {
|
|
1478
1556
|
type: "object",
|
|
1479
1557
|
properties: {
|
|
@@ -1483,15 +1561,21 @@ var TOOLS = [
|
|
|
1483
1561
|
},
|
|
1484
1562
|
issuesOnly: { type: "boolean", description: "Only return issues (warn/error/missing) for the match" },
|
|
1485
1563
|
conflictsOnly: { type: "boolean", description: "Only return PATH/version/ghost conflicts for the match" },
|
|
1486
|
-
offPathOnly: {
|
|
1564
|
+
offPathOnly: {
|
|
1565
|
+
type: "boolean",
|
|
1566
|
+
description: "Only return isolated off-PATH installs (version-manager envs excluded)"
|
|
1567
|
+
},
|
|
1487
1568
|
shells: { type: "string", description: "Shell views (see scan_environment)" },
|
|
1488
1569
|
disable: { type: "string", description: "Check-rule prefixes to skip (see scan_environment)" }
|
|
1489
|
-
}
|
|
1490
|
-
|
|
1570
|
+
},
|
|
1571
|
+
required: ["selector"]
|
|
1572
|
+
},
|
|
1573
|
+
outputSchema: QUERY_SCHEMA
|
|
1491
1574
|
},
|
|
1492
1575
|
{
|
|
1493
1576
|
name: "preflight",
|
|
1494
1577
|
description: "Agent pre-flight oracle: call this BEFORE running any shell command on the user's machine. " + "Returns a structured 'can this machine run my command cleanly right now' verdict -- Windows " + "constraints (execution policy, language mode, codepage, schannel revocation, app aliases, " + "safe-delete), mobile SDK state (Android/Flutter/Dart), and PATH conflict count. If 'blockers' " + "is non-empty the agent should fix (or ask the user to fix) those first, rather than discovering " + "failure mid-run (the gemini-cli #12519 'could not be parsed safely' class of failure).",
|
|
1578
|
+
annotations: { ...READ_ONLY, openWorldHint: false },
|
|
1495
1579
|
inputSchema: {
|
|
1496
1580
|
type: "object",
|
|
1497
1581
|
properties: {
|
|
@@ -1502,42 +1586,171 @@ var TOOLS = [
|
|
|
1502
1586
|
forAgent: {
|
|
1503
1587
|
type: "boolean",
|
|
1504
1588
|
description: "When true, emphasise agent-relevant constraints (language mode, execution policy, codepage)"
|
|
1589
|
+
},
|
|
1590
|
+
disable: {
|
|
1591
|
+
type: "string",
|
|
1592
|
+
description: "Comma-separated check-rule prefixes to skip, e.g. 'health.conda' to keep preflight fast"
|
|
1505
1593
|
}
|
|
1506
1594
|
}
|
|
1507
|
-
}
|
|
1595
|
+
},
|
|
1596
|
+
outputSchema: PREFLIGHT_SCHEMA
|
|
1508
1597
|
}
|
|
1509
1598
|
];
|
|
1510
|
-
|
|
1599
|
+
var TOOL_NAMES = new Set(TOOLS.map((t) => t.name));
|
|
1600
|
+
var ALL_SHELLS = ["current", "powershell", "gitbash", "wsl"];
|
|
1601
|
+
function parseShells(v) {
|
|
1602
|
+
if (typeof v !== "string" || !v)
|
|
1603
|
+
return ["current"];
|
|
1604
|
+
const list = v.split(",").map((s) => s.trim());
|
|
1605
|
+
return list.includes("all") ? ALL_SHELLS : list.length ? list : ["current"];
|
|
1606
|
+
}
|
|
1607
|
+
function parseDisable(v) {
|
|
1608
|
+
if (typeof v !== "string" || !v)
|
|
1609
|
+
return new Set;
|
|
1610
|
+
return new Set(v.split(",").map((s) => s.trim()).filter(Boolean));
|
|
1611
|
+
}
|
|
1612
|
+
function targetToShells(target) {
|
|
1613
|
+
if (typeof target === "string" && target) {
|
|
1614
|
+
const t = target.toLowerCase();
|
|
1615
|
+
if (t === "powershell")
|
|
1616
|
+
return ["powershell"];
|
|
1617
|
+
if (t === "cmd")
|
|
1618
|
+
return ["current"];
|
|
1619
|
+
if (t === "gitbash")
|
|
1620
|
+
return ["gitbash"];
|
|
1621
|
+
if (t === "wsl")
|
|
1622
|
+
return ["wsl"];
|
|
1623
|
+
}
|
|
1624
|
+
return ["current"];
|
|
1625
|
+
}
|
|
1626
|
+
function buildPreflight(manifest) {
|
|
1627
|
+
const win = manifest.windows || {};
|
|
1628
|
+
const sdks = manifest.sdks || {};
|
|
1629
|
+
const conflicts = manifest.conflicts || {};
|
|
1630
|
+
const pathConflicts = conflicts.pathConflicts || [];
|
|
1631
|
+
const checks = manifest.checks || [];
|
|
1632
|
+
const blockers = checks.filter((c) => c.Severity === "error").map((c) => c.ID);
|
|
1633
|
+
const warnings = checks.filter((c) => c.Severity === "warn").map((c) => c.ID);
|
|
1634
|
+
return {
|
|
1635
|
+
ok: blockers.length === 0,
|
|
1636
|
+
blockers,
|
|
1637
|
+
warnings,
|
|
1638
|
+
executionPolicy: win.executionPolicy ?? null,
|
|
1639
|
+
languageMode: win.languageMode ?? null,
|
|
1640
|
+
codepage: win.codepage ?? null,
|
|
1641
|
+
schannelRevoke: win.schannelRevokeCheck ?? null,
|
|
1642
|
+
windows: {
|
|
1643
|
+
present: !!win.windows,
|
|
1644
|
+
appAliases: (win.appAliases || []).length,
|
|
1645
|
+
safeDelete: !!win.safeDeleteActive
|
|
1646
|
+
},
|
|
1647
|
+
sdk: {
|
|
1648
|
+
android: sdks.android ? { sdkHome: sdks.android.sdkHome, ndk: sdks.android.ndk || [], flutterChannel: sdks.flutter?.channel ?? null } : null,
|
|
1649
|
+
flutter: sdks.flutter ? { version: sdks.flutter.version, channel: sdks.flutter.channel } : null,
|
|
1650
|
+
dart: sdks.dart ? { version: sdks.dart.version } : null
|
|
1651
|
+
},
|
|
1652
|
+
pathConflicts: pathConflicts.length
|
|
1653
|
+
};
|
|
1654
|
+
}
|
|
1655
|
+
function wrap(structured) {
|
|
1656
|
+
return {
|
|
1657
|
+
content: [{ type: "text", text: JSON.stringify(structured, null, 2) }],
|
|
1658
|
+
structuredContent: structured,
|
|
1659
|
+
isError: false
|
|
1660
|
+
};
|
|
1661
|
+
}
|
|
1662
|
+
async function callTool(name, rawArgs, deps = {}) {
|
|
1663
|
+
const scan = deps.scan ?? runScan;
|
|
1664
|
+
const query = deps.query ?? queryManifest;
|
|
1665
|
+
const args = rawArgs && typeof rawArgs === "object" && !Array.isArray(rawArgs) ? rawArgs : {};
|
|
1511
1666
|
if (name === "scan_environment") {
|
|
1512
|
-
const manifest = await
|
|
1667
|
+
const manifest = await scan(parseShells(args.shells), parseDisable(args.disable), {
|
|
1513
1668
|
silent: true,
|
|
1514
1669
|
auditDeps: args.auditDeps === true,
|
|
1515
1670
|
healthNetwork: args.healthNetwork === true,
|
|
1516
1671
|
scanSecrets: args.scanSecrets === true
|
|
1517
1672
|
});
|
|
1518
|
-
return
|
|
1673
|
+
return wrap(manifest);
|
|
1519
1674
|
}
|
|
1520
1675
|
if (name === "query_tool") {
|
|
1521
|
-
const manifest = await
|
|
1522
|
-
const result =
|
|
1676
|
+
const manifest = await scan(parseShells(args.shells), parseDisable(args.disable), { silent: true });
|
|
1677
|
+
const result = query(manifest, {
|
|
1523
1678
|
selector: typeof args.selector === "string" ? args.selector : undefined,
|
|
1524
1679
|
issues: args.issuesOnly === true,
|
|
1525
1680
|
conflicts: args.conflictsOnly === true,
|
|
1526
1681
|
offPath: args.offPathOnly === true
|
|
1527
1682
|
});
|
|
1528
|
-
return
|
|
1683
|
+
return wrap(result);
|
|
1529
1684
|
}
|
|
1530
1685
|
if (name === "preflight") {
|
|
1531
|
-
const manifest = await
|
|
1686
|
+
const manifest = await scan(targetToShells(args.target), parseDisable(args.disable), {
|
|
1532
1687
|
silent: true,
|
|
1533
1688
|
fast: true
|
|
1534
1689
|
});
|
|
1535
|
-
return
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1690
|
+
return wrap(buildPreflight(manifest));
|
|
1691
|
+
}
|
|
1692
|
+
throw new Error(`unknown tool: ${name}`);
|
|
1693
|
+
}
|
|
1694
|
+
var ok = (id, result) => ({ jsonrpc: "2.0", id, result });
|
|
1695
|
+
var fail = (id, code, message) => ({ jsonrpc: "2.0", id, error: { code, message } });
|
|
1696
|
+
function negotiateProtocol(requested) {
|
|
1697
|
+
if (typeof requested === "string" && SUPPORTED_PROTOCOLS.includes(requested)) {
|
|
1698
|
+
return requested;
|
|
1699
|
+
}
|
|
1700
|
+
return PREFERRED_PROTOCOL;
|
|
1701
|
+
}
|
|
1702
|
+
function discoverResult(deps) {
|
|
1703
|
+
return {
|
|
1704
|
+
protocolVersion: PREFERRED_PROTOCOL,
|
|
1705
|
+
capabilities: { tools: {} },
|
|
1706
|
+
serverInfo: deps.serverInfo ?? SERVER_INFO
|
|
1707
|
+
};
|
|
1708
|
+
}
|
|
1709
|
+
async function handleMessage(msg, deps = {}) {
|
|
1710
|
+
if (!msg || typeof msg !== "object" || Array.isArray(msg))
|
|
1711
|
+
return fail(null, -32600, "invalid request");
|
|
1712
|
+
const id = msg.id;
|
|
1713
|
+
const method = msg.method;
|
|
1714
|
+
if (typeof method !== "string" || !method) {
|
|
1715
|
+
return id === undefined ? null : fail(id, -32600, "missing method");
|
|
1716
|
+
}
|
|
1717
|
+
const params = msg.params && typeof msg.params === "object" ? msg.params : {};
|
|
1718
|
+
switch (method) {
|
|
1719
|
+
case "initialize":
|
|
1720
|
+
return ok(id, {
|
|
1721
|
+
protocolVersion: negotiateProtocol(params.protocolVersion),
|
|
1722
|
+
capabilities: { tools: {} },
|
|
1723
|
+
serverInfo: deps.serverInfo ?? SERVER_INFO,
|
|
1724
|
+
instructions: "devmap is a read-only environment oracle. Call `preflight` before running shell commands; " + "call `scan_environment` when you need the full manifest."
|
|
1725
|
+
});
|
|
1726
|
+
case "server/discover":
|
|
1727
|
+
return ok(id, discoverResult(deps));
|
|
1728
|
+
case "notifications/initialized":
|
|
1729
|
+
case "initialized":
|
|
1730
|
+
case "notifications/cancelled":
|
|
1731
|
+
return null;
|
|
1732
|
+
case "ping":
|
|
1733
|
+
return ok(id, {});
|
|
1734
|
+
case "tools/list":
|
|
1735
|
+
return ok(id, { tools: TOOLS, ttlMs: TOOLS_TTL_MS, cacheScope: TOOLS_CACHE_SCOPE });
|
|
1736
|
+
case "tools/call": {
|
|
1737
|
+
const name = params.name;
|
|
1738
|
+
if (typeof name !== "string" || !name)
|
|
1739
|
+
return fail(id, -32602, "missing tool name");
|
|
1740
|
+
if (!TOOL_NAMES.has(name))
|
|
1741
|
+
return fail(id, -32602, `unknown tool: ${name}`);
|
|
1742
|
+
try {
|
|
1743
|
+
return ok(id, await callTool(name, params.arguments, deps));
|
|
1744
|
+
} catch (e) {
|
|
1745
|
+
return ok(id, {
|
|
1746
|
+
content: [{ type: "text", text: "error: " + (e?.message || String(e)) }],
|
|
1747
|
+
isError: true
|
|
1748
|
+
});
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
default:
|
|
1752
|
+
return id === undefined ? null : fail(id, -32601, `method not found: ${method}`);
|
|
1539
1753
|
}
|
|
1540
|
-
return { content: [{ type: "text", text: `unknown tool: ${name}` }], isError: true };
|
|
1541
1754
|
}
|
|
1542
1755
|
async function startMcpServer() {
|
|
1543
1756
|
const toErr = (...a) => process.stderr.write(a.map((x) => typeof x === "string" ? x : String(x)).join(" ") + `
|
|
@@ -1567,52 +1780,10 @@ async function startMcpServer() {
|
|
|
1567
1780
|
log("[mcp] dropping malformed frame");
|
|
1568
1781
|
continue;
|
|
1569
1782
|
}
|
|
1570
|
-
|
|
1571
|
-
const
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
if (id !== undefined)
|
|
1575
|
-
write({ jsonrpc: "2.0", id, error: { code: -32600, message: "missing method" } });
|
|
1576
|
-
continue;
|
|
1577
|
-
}
|
|
1578
|
-
switch (method) {
|
|
1579
|
-
case "initialize":
|
|
1580
|
-
write({
|
|
1581
|
-
jsonrpc: "2.0",
|
|
1582
|
-
id,
|
|
1583
|
-
result: {
|
|
1584
|
-
protocolVersion: msg.params?.protocolVersion || "2024-11-05",
|
|
1585
|
-
capabilities: { tools: {} },
|
|
1586
|
-
serverInfo: { name: "devmap", version: VERSION }
|
|
1587
|
-
}
|
|
1588
|
-
});
|
|
1589
|
-
break;
|
|
1590
|
-
case "notifications/initialized":
|
|
1591
|
-
case "initialized":
|
|
1592
|
-
case "notifications/cancelled":
|
|
1593
|
-
break;
|
|
1594
|
-
case "ping":
|
|
1595
|
-
write({ jsonrpc: "2.0", id, result: {} });
|
|
1596
|
-
break;
|
|
1597
|
-
case "tools/list":
|
|
1598
|
-
write({ jsonrpc: "2.0", id, result: { tools: TOOLS } });
|
|
1599
|
-
break;
|
|
1600
|
-
case "tools/call":
|
|
1601
|
-
try {
|
|
1602
|
-
const r = await callTool(msg.params?.name, msg.params?.arguments || {});
|
|
1603
|
-
write({ jsonrpc: "2.0", id, result: r });
|
|
1604
|
-
} catch (e) {
|
|
1605
|
-
write({
|
|
1606
|
-
jsonrpc: "2.0",
|
|
1607
|
-
id,
|
|
1608
|
-
result: { content: [{ type: "text", text: "error: " + (e?.message || String(e)) }], isError: true }
|
|
1609
|
-
});
|
|
1610
|
-
}
|
|
1611
|
-
break;
|
|
1612
|
-
default:
|
|
1613
|
-
if (id !== undefined)
|
|
1614
|
-
write({ jsonrpc: "2.0", id, error: { code: -32601, message: `method not found: ${method}` } });
|
|
1615
|
-
}
|
|
1783
|
+
log("[mcp] ->", msg.method || "?", msg.id ?? "");
|
|
1784
|
+
const res = await handleMessage(msg);
|
|
1785
|
+
if (res !== null)
|
|
1786
|
+
write(res);
|
|
1616
1787
|
}
|
|
1617
1788
|
}
|
|
1618
1789
|
log("[mcp] stdin closed, shutting down");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devmap
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Map your machine's dev environment and surface issues (PATH conflicts, ghost binaries, multi-version collisions). fastfetch-for-dev-tools. This PyPI package ships the real devmap CLI (a bundled JavaScript app launched via Node.js or Bun), so `pip install devmap && devmap` works standalone.
|
|
5
5
|
Author: devmap contributors
|
|
6
6
|
License: MIT
|
|
@@ -109,7 +109,7 @@ Register it with any MCP-capable agent (Cursor / Cline / Claude Desktop / Codex
|
|
|
109
109
|
}
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
Three tools are exposed
|
|
112
|
+
Three tools are exposed. The server targets **MCP `2026-07-28`** — stateless core (`server/discover`, no handshake required), tool `annotations` (`readOnlyHint`), JSON Schema `outputSchema` + `structuredContent` results, and cacheable `tools/list` — while still answering the legacy `initialize` handshake for older clients.
|
|
113
113
|
|
|
114
114
|
| Tool | Purpose |
|
|
115
115
|
|------|---------|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "devmap"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.3"
|
|
8
8
|
description = "Map your machine's dev environment and surface issues (PATH conflicts, ghost binaries, multi-version collisions). fastfetch-for-dev-tools. This PyPI package ships the real devmap CLI (a bundled JavaScript app launched via Node.js or Bun), so `pip install devmap && devmap` works standalone."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|