infinitecampus-mcp 2.8.2 → 2.8.4
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/bundle.js +2984 -1390
- package/dist/index.js +57 -26
- package/package.json +6 -6
- package/server.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { dirname, join } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
-
import { loadDotenvSafely, runMcp } from '@chrischall/mcp-utils';
|
|
4
|
+
import { loadDotenvSafely, McpToolError, runMcp } from '@chrischall/mcp-utils';
|
|
5
5
|
// quiet load of the local .env (no-throw, silent when the file is absent —
|
|
6
6
|
// e.g. inside an mcpb bundle). Path is resolved next to dist/ so the same
|
|
7
7
|
// `..`/.env that the previous inline dotenv call used still applies.
|
|
@@ -35,7 +35,7 @@ const AI_NOTICE = '[infinitecampus-mcp] Developed and maintained by AI (Claude).
|
|
|
35
35
|
// Defer config errors so the server can still start cleanly when env vars
|
|
36
36
|
// aren't set (e.g. during the host's install-time smoke test, before the
|
|
37
37
|
// user has filled in user_config OR the user hasn't yet signed into their
|
|
38
|
-
// IC portal in the browser). When not configured
|
|
38
|
+
// IC portal in the browser). When not configured every tool still registers and
|
|
39
39
|
// log a clear stderr message — far better than the previous crash loop.
|
|
40
40
|
let account = null;
|
|
41
41
|
let refreshSession;
|
|
@@ -51,21 +51,61 @@ catch (e) {
|
|
|
51
51
|
configError = e;
|
|
52
52
|
}
|
|
53
53
|
// Hand off to mcp-utils' runMcp for the connect + stdio transport + graceful
|
|
54
|
-
// shutdown.
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
// the host's install-time tools/list still succeeds and the user gets an
|
|
58
|
-
// actionable stderr message (banner) instead of a crash loop.
|
|
54
|
+
// shutdown. The registrar list is the SAME either way; only the client and the
|
|
55
|
+
// banner differ. A tool surface that follows the environment is what this
|
|
56
|
+
// avoids — see `unconfiguredClient`.
|
|
59
57
|
const COMMON = {
|
|
60
58
|
name: 'infinitecampus',
|
|
61
|
-
version: '2.8.
|
|
59
|
+
version: '2.8.4', // x-release-please-version
|
|
62
60
|
};
|
|
63
61
|
// Shared with the healthcheck so it can report the SAME state the tools see,
|
|
64
62
|
// including on the unconfigured path where there are no tools at all.
|
|
65
63
|
const healthState = { account, source, configError, client: null };
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Stands in for the client when configuration is missing, so that every tool
|
|
66
|
+
* registers either way and the failure surfaces WHERE IT IS ACTIONABLE — in the
|
|
67
|
+
* answer to the tool somebody called, not in a tool list they never saw.
|
|
68
|
+
*
|
|
69
|
+
* The surface must not follow the environment. This server is hosted with
|
|
70
|
+
* `perUserChild` + `authFields`, so mcp-host spawns a principal-less child with
|
|
71
|
+
* none of the per-user config for prewarm, auto-update, restart and every
|
|
72
|
+
* admin-portal tool listing — and THAT child's list is what the portal
|
|
73
|
+
* publishes as the connector's surface. It advertised one tool for a connector
|
|
74
|
+
* that has twenty.
|
|
75
|
+
*
|
|
76
|
+
* This continues the reasoning that put the healthcheck on this path rather
|
|
77
|
+
* than reversing it: a server that can explain itself beats one that cannot,
|
|
78
|
+
* and nineteen tools that each name the missing variables explain it better
|
|
79
|
+
* than nineteen absences do. The healthcheck still reports the same state, and
|
|
80
|
+
* `healthState.client` deliberately stays null so it reports "unconfigured"
|
|
81
|
+
* rather than mistaking this stand-in for a live client.
|
|
82
|
+
*/
|
|
83
|
+
function unconfiguredClient(reason) {
|
|
84
|
+
const fail = () => {
|
|
85
|
+
throw new McpToolError(`infinitecampus-mcp is not configured: ${reason?.message ?? 'unknown error'}`, {
|
|
86
|
+
hint: 'Set IC_BASE_URL (your portal URL) and IC_DISTRICT (the app-name path segment), ' +
|
|
87
|
+
'plus IC_USERNAME and IC_PASSWORD together if you are not signing in through the ' +
|
|
88
|
+
'browser. Call ic_healthcheck for the resolved state.',
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
return new Proxy({}, {
|
|
92
|
+
get(_target, prop) {
|
|
93
|
+
// `then` must answer undefined or this object is thenable, and any
|
|
94
|
+
// `await client` would resolve to something other than the client.
|
|
95
|
+
// Symbols (toStringTag, node's inspect) are asked for by the runtime
|
|
96
|
+
// rather than by tool code, so they get the same treatment.
|
|
97
|
+
if (typeof prop === 'symbol' || prop === 'then')
|
|
98
|
+
return undefined;
|
|
99
|
+
return fail;
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
{
|
|
104
|
+
const client = account
|
|
105
|
+
? new ICClient(account, { refreshSession })
|
|
106
|
+
: unconfiguredClient(configError);
|
|
107
|
+
if (account)
|
|
108
|
+
healthState.client = client;
|
|
69
109
|
const tools = [
|
|
70
110
|
(server) => registerHealthcheckTools(server, healthState),
|
|
71
111
|
registerDistrictTools,
|
|
@@ -87,19 +127,10 @@ if (account) {
|
|
|
87
127
|
registerFeaturesTools,
|
|
88
128
|
];
|
|
89
129
|
const suffix = source === 'fetchproxy' ? ' [via fetchproxy]' : '';
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
// NOT `tools: []` any more. A server that registers nothing explains itself
|
|
97
|
-
// only on stderr, which a hosted connector never sees — so a misconfigured
|
|
98
|
-
// server was indistinguishable from a broken one. The healthcheck is the one
|
|
99
|
-
// tool that must survive this path, because this is the path that needs it.
|
|
100
|
-
await runMcp({
|
|
101
|
-
...COMMON,
|
|
102
|
-
tools: [(server) => registerHealthcheckTools(server, healthState)],
|
|
103
|
-
banner: `${notConfigured}\n${AI_NOTICE}`,
|
|
104
|
-
});
|
|
130
|
+
const banner = account
|
|
131
|
+
? `[infinitecampus-mcp] District: ${account.name} (${account.baseUrl})${suffix}`
|
|
132
|
+
: `[infinitecampus-mcp] Not configured: ${configError?.message ?? 'unknown error'}\n` +
|
|
133
|
+
'[infinitecampus-mcp] Every tool is registered and will report this until the ' +
|
|
134
|
+
'required env vars are set. Call ic_healthcheck for the resolved state.';
|
|
135
|
+
await runMcp({ ...COMMON, deps: client, tools, banner: `${banner}\n${AI_NOTICE}` });
|
|
105
136
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "infinitecampus-mcp",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.4",
|
|
4
4
|
"mcpName": "io.github.chrischall/infinitecampus-mcp",
|
|
5
5
|
"description": "Infinite Campus (Campus Parent) MCP server — multi-district read + message/document write",
|
|
6
6
|
"author": "Claude Code (AI) <https://www.anthropic.com/claude>",
|
|
@@ -45,13 +45,13 @@
|
|
|
45
45
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@chrischall/mcp-utils": "^0.
|
|
49
|
-
"@fetchproxy/bootstrap": "^
|
|
50
|
-
"@fetchproxy/server": "^
|
|
51
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
48
|
+
"@chrischall/mcp-utils": "^0.26.1",
|
|
49
|
+
"@fetchproxy/bootstrap": "^3.0.0",
|
|
50
|
+
"@fetchproxy/server": "^3.0.0",
|
|
51
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
52
52
|
"dotenv": "^17.4.2",
|
|
53
53
|
"node-html-parser": "^9.0.0",
|
|
54
|
-
"zod": "^4.4
|
|
54
|
+
"zod": "^4.5.4"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/node": "^26.0.0",
|
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/chrischall/infinitecampus-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "2.8.
|
|
9
|
+
"version": "2.8.4",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "infinitecampus-mcp",
|
|
14
|
-
"version": "2.8.
|
|
14
|
+
"version": "2.8.4",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|