@dashflow/ms365-mcp-server 1.0.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/.env.example +54 -0
- package/.releaserc.json +9 -0
- package/Dockerfile +22 -0
- package/LICENSE +21 -0
- package/README.md +590 -0
- package/bin/generate-graph-client.mjs +59 -0
- package/bin/modules/download-openapi.mjs +40 -0
- package/bin/modules/extract-descriptions.mjs +48 -0
- package/bin/modules/generate-mcp-tools.mjs +46 -0
- package/bin/modules/simplified-openapi.mjs +694 -0
- package/dist/auth-tools.js +202 -0
- package/dist/auth.js +422 -0
- package/dist/cli.js +78 -0
- package/dist/cloud-config.js +49 -0
- package/dist/endpoints.json +596 -0
- package/dist/generated/endpoint-types.js +0 -0
- package/dist/generated/hack.js +42 -0
- package/dist/graph-client.js +208 -0
- package/dist/graph-tools.js +401 -0
- package/dist/index.js +76 -0
- package/dist/lib/microsoft-auth.js +73 -0
- package/dist/logger.js +42 -0
- package/dist/oauth-provider.js +51 -0
- package/dist/request-context.js +9 -0
- package/dist/secrets.js +68 -0
- package/dist/server.js +387 -0
- package/dist/tool-categories.js +93 -0
- package/dist/version.js +10 -0
- package/eslint.config.js +43 -0
- package/glama.json +4 -0
- package/package.json +79 -0
- package/remove-recursive-refs.js +294 -0
- package/src/endpoints.json +596 -0
- package/src/generated/README.md +56 -0
- package/src/generated/endpoint-types.ts +27 -0
- package/src/generated/hack.ts +49 -0
- package/test-calendar-fix.js +62 -0
- package/test-real-calendar.js +96 -0
- package/tsup.config.ts +30 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Endpoint, Parameter } from './endpoint-types.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
export function makeApi(endpoints: Endpoint[]) {
|
|
5
|
+
return endpoints;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class Zodios {
|
|
9
|
+
endpoints: Endpoint[];
|
|
10
|
+
|
|
11
|
+
constructor(baseUrlOrEndpoints: Endpoint[] | string, endpoints?: any, options?: any) {
|
|
12
|
+
if (typeof baseUrlOrEndpoints === 'string') {
|
|
13
|
+
throw new Error('No such hack');
|
|
14
|
+
}
|
|
15
|
+
this.endpoints = baseUrlOrEndpoints.map((endpoint) => {
|
|
16
|
+
endpoint.parameters = endpoint.parameters || [];
|
|
17
|
+
for (const parameter of endpoint.parameters) {
|
|
18
|
+
parameter.name = parameter.name.replace(/[$_]+/g, '');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const pathParamRegex = /:([a-zA-Z0-9]+)/g;
|
|
22
|
+
const pathParams = [];
|
|
23
|
+
let match;
|
|
24
|
+
while ((match = pathParamRegex.exec(endpoint.path)) !== null) {
|
|
25
|
+
pathParams.push(match[1]);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
for (const pathParam of pathParams) {
|
|
29
|
+
const paramExists = endpoint.parameters.some(
|
|
30
|
+
(param) => param.name === pathParam || param.name === pathParam.replace(/[$_]+/g, '')
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
if (!paramExists) {
|
|
34
|
+
const newParam: Parameter = {
|
|
35
|
+
name: pathParam,
|
|
36
|
+
type: 'Path',
|
|
37
|
+
schema: z.string().describe(`Path parameter: ${pathParam}`),
|
|
38
|
+
description: `Path parameter: ${pathParam}`,
|
|
39
|
+
};
|
|
40
|
+
endpoint.parameters.push(newParam);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return endpoint;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type ZodiosOptions = {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Test script to verify the calendarId parameter fix
|
|
4
|
+
// This simulates what the MCP client would do
|
|
5
|
+
|
|
6
|
+
import { spawn } from 'child_process';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { dirname, join } from 'path';
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = dirname(__filename);
|
|
12
|
+
|
|
13
|
+
// Start the MCP server
|
|
14
|
+
const server = spawn('node', [join(__dirname, 'dist', 'index.js'), '-v'], {
|
|
15
|
+
stdio: ['pipe', 'pipe', 'inherit'],
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Wait a bit for server to start
|
|
19
|
+
setTimeout(() => {
|
|
20
|
+
// Test the create-calendar-event with calendarId
|
|
21
|
+
const testRequest = {
|
|
22
|
+
jsonrpc: '2.0',
|
|
23
|
+
method: 'tools/call',
|
|
24
|
+
params: {
|
|
25
|
+
name: 'create-calendar-event',
|
|
26
|
+
arguments: {
|
|
27
|
+
calendarId: 'EXAMPLE_CALENDAR_ID_HERE',
|
|
28
|
+
body: {
|
|
29
|
+
subject: 'Test Event on Specific Calendar',
|
|
30
|
+
body: {
|
|
31
|
+
contentType: 'text',
|
|
32
|
+
content: 'Testing calendarId parameter fix',
|
|
33
|
+
},
|
|
34
|
+
start: {
|
|
35
|
+
dateTime: '2025-12-01T10:00:00.0000000',
|
|
36
|
+
timeZone: 'America/New_York',
|
|
37
|
+
},
|
|
38
|
+
end: {
|
|
39
|
+
dateTime: '2025-12-01T11:00:00.0000000',
|
|
40
|
+
timeZone: 'America/New_York',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
id: 1,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
console.log('Sending test request:', JSON.stringify(testRequest, null, 2));
|
|
49
|
+
|
|
50
|
+
server.stdin.write(JSON.stringify(testRequest) + '\n');
|
|
51
|
+
|
|
52
|
+
// Read response
|
|
53
|
+
server.stdout.on('data', (data) => {
|
|
54
|
+
console.log('Response:', data.toString());
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Close after a few seconds
|
|
58
|
+
setTimeout(() => {
|
|
59
|
+
server.kill();
|
|
60
|
+
process.exit(0);
|
|
61
|
+
}, 5000);
|
|
62
|
+
}, 2000);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Direct test of the calendar fix using our local build
|
|
4
|
+
import GraphClient from './dist/graph-client.js';
|
|
5
|
+
import { registerGraphTools } from './dist/graph-tools.js';
|
|
6
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
|
|
8
|
+
async function testCalendarFix() {
|
|
9
|
+
console.log('Testing calendar fix with Specific Calendar...\n');
|
|
10
|
+
|
|
11
|
+
// Initialize the graph client
|
|
12
|
+
const graphClient = new GraphClient();
|
|
13
|
+
|
|
14
|
+
// Check if we're logged in
|
|
15
|
+
try {
|
|
16
|
+
await graphClient.ensureAuthenticated();
|
|
17
|
+
console.log('✓ Authenticated successfully\n');
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.error('Authentication failed. Please run: npm run dev -- --login');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Test parameters
|
|
24
|
+
const exampleCalendarId = 'EXAMPLE_CALENDAR_ID_HERE';
|
|
25
|
+
|
|
26
|
+
const testEvent = {
|
|
27
|
+
subject: 'TEST - Calendar Fix Verification',
|
|
28
|
+
body: {
|
|
29
|
+
contentType: 'text',
|
|
30
|
+
content: 'This test verifies that events can be created on the Specific Calendar',
|
|
31
|
+
},
|
|
32
|
+
start: {
|
|
33
|
+
dateTime: '2025-12-20T10:00:00',
|
|
34
|
+
timeZone: 'America/New_York',
|
|
35
|
+
},
|
|
36
|
+
end: {
|
|
37
|
+
dateTime: '2025-12-20T11:00:00',
|
|
38
|
+
timeZone: 'America/New_York',
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Build the path with our fix
|
|
43
|
+
const path = `/me/calendars/${encodeURIComponent(exampleCalendarId)}/events`;
|
|
44
|
+
console.log('Using path:', path);
|
|
45
|
+
console.log('');
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
// Make the request
|
|
49
|
+
const response = await graphClient.graphRequest(path, {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
body: JSON.stringify(testEvent),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const result = JSON.parse(response.content[0].text);
|
|
55
|
+
console.log('✓ Event created successfully!');
|
|
56
|
+
console.log(' Event ID:', result.id);
|
|
57
|
+
console.log(' Subject:', result.subject);
|
|
58
|
+
console.log('');
|
|
59
|
+
|
|
60
|
+
// Verify it's on the correct calendar by checking the event
|
|
61
|
+
console.log('Verifying calendar placement...');
|
|
62
|
+
const getPath = `/me/events/${result.id}`;
|
|
63
|
+
const verifyResponse = await graphClient.graphRequest(getPath, {
|
|
64
|
+
method: 'GET',
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const event = JSON.parse(verifyResponse.content[0].text);
|
|
68
|
+
|
|
69
|
+
// The calendar link should contain the Specific Calendar ID
|
|
70
|
+
if (
|
|
71
|
+
event['calendar@odata.navigationLink'] &&
|
|
72
|
+
event['calendar@odata.navigationLink'].includes(exampleCalendarId)
|
|
73
|
+
) {
|
|
74
|
+
console.log('✅ SUCCESS! Event was created on the Specific Calendar!');
|
|
75
|
+
} else {
|
|
76
|
+
console.log('❌ Event was created but on the wrong calendar');
|
|
77
|
+
console.log('Calendar link:', event['calendar@odata.navigationLink']);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Clean up - delete the test event
|
|
81
|
+
console.log('\nCleaning up test event...');
|
|
82
|
+
await graphClient.graphRequest(`/me/events/${result.id}`, {
|
|
83
|
+
method: 'DELETE',
|
|
84
|
+
});
|
|
85
|
+
console.log('✓ Test event deleted');
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error('Error creating event:', error.message);
|
|
88
|
+
if (error.response) {
|
|
89
|
+
console.error('Response:', error.response);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
process.exit(0);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
testCalendarFix().catch(console.error);
|
package/tsup.config.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { defineConfig } from 'tsup';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
entry: ['src/**/*.ts', 'src/endpoints.json'],
|
|
5
|
+
format: ['esm'],
|
|
6
|
+
target: 'es2020',
|
|
7
|
+
outDir: 'dist',
|
|
8
|
+
clean: true,
|
|
9
|
+
bundle: false,
|
|
10
|
+
splitting: false,
|
|
11
|
+
sourcemap: false,
|
|
12
|
+
dts: false,
|
|
13
|
+
publicDir: false,
|
|
14
|
+
onSuccess: 'chmod +x dist/index.js',
|
|
15
|
+
loader: {
|
|
16
|
+
'.json': 'copy',
|
|
17
|
+
},
|
|
18
|
+
noExternal: [],
|
|
19
|
+
external: [
|
|
20
|
+
'@azure/msal-node',
|
|
21
|
+
'@modelcontextprotocol/sdk',
|
|
22
|
+
'commander',
|
|
23
|
+
'dotenv',
|
|
24
|
+
'express',
|
|
25
|
+
'js-yaml',
|
|
26
|
+
'keytar',
|
|
27
|
+
'winston',
|
|
28
|
+
'zod',
|
|
29
|
+
],
|
|
30
|
+
});
|