@wonderwhy-er/desktop-commander 0.2.38 → 0.2.40

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.
Files changed (263) hide show
  1. package/README.md +53 -2
  2. package/dist/handlers/filesystem-handlers.d.ts +5 -0
  3. package/dist/handlers/filesystem-handlers.js +14 -2
  4. package/dist/remote-device/desktop-commander-integration.js +1 -1
  5. package/dist/search-manager.js +31 -38
  6. package/dist/server.js +9 -4
  7. package/dist/terminal-manager.js +4 -2
  8. package/dist/tools/edit.js +34 -1
  9. package/dist/tools/filesystem.js +91 -3
  10. package/dist/tools/improved-process-tools.js +2 -1
  11. package/dist/ui/config-editor/config-editor-runtime.js +65 -14096
  12. package/dist/ui/config-editor/styles.css +2 -1
  13. package/dist/ui/file-preview/preview-runtime.js +435 -26533
  14. package/dist/ui/file-preview/shared/preview-file-types.d.ts +1 -1
  15. package/dist/ui/file-preview/src/app.d.ts +1 -5
  16. package/dist/ui/file-preview/src/app.js +384 -534
  17. package/dist/ui/file-preview/src/components/markdown-renderer.js +47 -9
  18. package/dist/ui/file-preview/src/directory-controller.d.ts +8 -0
  19. package/dist/ui/file-preview/src/directory-controller.js +233 -0
  20. package/dist/ui/file-preview/src/document-layout.d.ts +20 -0
  21. package/dist/ui/file-preview/src/document-layout.js +109 -0
  22. package/dist/ui/file-preview/src/document-outline.d.ts +17 -0
  23. package/dist/ui/file-preview/src/document-outline.js +97 -0
  24. package/dist/ui/file-preview/src/document-workspace.d.ts +19 -0
  25. package/dist/ui/file-preview/src/document-workspace.js +33 -0
  26. package/dist/ui/file-preview/src/file-type-handlers.d.ts +10 -0
  27. package/dist/ui/file-preview/src/file-type-handlers.js +98 -0
  28. package/dist/ui/file-preview/src/host/external-actions.d.ts +19 -0
  29. package/dist/ui/file-preview/src/host/external-actions.js +94 -0
  30. package/dist/ui/file-preview/src/host/selection-context.d.ts +9 -0
  31. package/dist/ui/file-preview/src/host/selection-context.js +106 -0
  32. package/dist/ui/file-preview/src/markdown/conflict-dialog.d.ts +40 -0
  33. package/dist/ui/file-preview/src/markdown/conflict-dialog.js +163 -0
  34. package/dist/ui/file-preview/src/markdown/controller.d.ts +44 -0
  35. package/dist/ui/file-preview/src/markdown/controller.js +1040 -0
  36. package/dist/ui/file-preview/src/markdown/editor.d.ts +131 -0
  37. package/dist/ui/file-preview/src/markdown/editor.js +1479 -0
  38. package/dist/ui/file-preview/src/markdown/linking.d.ts +16 -0
  39. package/dist/ui/file-preview/src/markdown/linking.js +228 -0
  40. package/dist/ui/file-preview/src/markdown/outline.d.ts +2 -0
  41. package/dist/ui/file-preview/src/markdown/outline.js +16 -0
  42. package/dist/ui/file-preview/src/markdown/parser.d.ts +30 -0
  43. package/dist/ui/file-preview/src/markdown/parser.js +38 -0
  44. package/dist/ui/file-preview/src/markdown/preview.d.ts +1 -0
  45. package/dist/ui/file-preview/src/markdown/preview.js +20 -0
  46. package/dist/ui/file-preview/src/markdown/slugify.d.ts +3 -0
  47. package/dist/ui/file-preview/src/markdown/slugify.js +31 -0
  48. package/dist/ui/file-preview/src/markdown/utils.d.ts +1 -0
  49. package/dist/ui/file-preview/src/markdown/utils.js +15 -0
  50. package/dist/ui/file-preview/src/model.d.ts +35 -0
  51. package/dist/ui/file-preview/src/panel-actions.d.ts +17 -0
  52. package/dist/ui/file-preview/src/panel-actions.js +182 -0
  53. package/dist/ui/file-preview/src/path-utils.d.ts +6 -0
  54. package/dist/ui/file-preview/src/path-utils.js +64 -0
  55. package/dist/ui/file-preview/src/payload-utils.d.ts +11 -0
  56. package/dist/ui/file-preview/src/payload-utils.js +94 -0
  57. package/dist/ui/file-preview/styles.css +1066 -233
  58. package/dist/ui/shared/widget-state.d.ts +6 -1
  59. package/dist/ui/shared/widget-state.js +102 -4
  60. package/dist/utils/capture.js +1 -1
  61. package/dist/utils/files/base.d.ts +2 -0
  62. package/dist/utils/open-browser.js +1 -1
  63. package/dist/utils/toolHistory.d.ts +13 -0
  64. package/dist/utils/toolHistory.js +65 -0
  65. package/dist/version.d.ts +1 -1
  66. package/dist/version.js +1 -1
  67. package/package.json +12 -1
  68. package/dist/data/spec-kit-prompts.json +0 -123
  69. package/dist/handlers/macos-control-handlers.d.ts +0 -16
  70. package/dist/handlers/macos-control-handlers.js +0 -81
  71. package/dist/handlers/node-handlers.d.ts +0 -6
  72. package/dist/handlers/node-handlers.js +0 -73
  73. package/dist/handlers/test-crash-handler.d.ts +0 -11
  74. package/dist/handlers/test-crash-handler.js +0 -26
  75. package/dist/http-index.d.ts +0 -45
  76. package/dist/http-index.js +0 -51
  77. package/dist/http-server-auto-tunnel.js +0 -667
  78. package/dist/http-server-named-tunnel.d.ts +0 -2
  79. package/dist/http-server-named-tunnel.js +0 -167
  80. package/dist/http-server-tunnel.d.ts +0 -2
  81. package/dist/http-server-tunnel.js +0 -111
  82. package/dist/http-server.d.ts +0 -2
  83. package/dist/http-server.js +0 -270
  84. package/dist/index-oauth.d.ts +0 -2
  85. package/dist/index-oauth.js +0 -201
  86. package/dist/lib.d.ts +0 -10
  87. package/dist/lib.js +0 -10
  88. package/dist/oauth/auth-middleware.d.ts +0 -20
  89. package/dist/oauth/auth-middleware.js +0 -62
  90. package/dist/oauth/index.d.ts +0 -3
  91. package/dist/oauth/index.js +0 -3
  92. package/dist/oauth/oauth-manager.d.ts +0 -80
  93. package/dist/oauth/oauth-manager.js +0 -179
  94. package/dist/oauth/oauth-routes.d.ts +0 -3
  95. package/dist/oauth/oauth-routes.js +0 -377
  96. package/dist/oauth/provider.d.ts +0 -22
  97. package/dist/oauth/provider.js +0 -124
  98. package/dist/oauth/server.d.ts +0 -18
  99. package/dist/oauth/server.js +0 -160
  100. package/dist/oauth/types.d.ts +0 -54
  101. package/dist/oauth/types.js +0 -2
  102. package/dist/remote-device/templates/auth-success.d.ts +0 -1
  103. package/dist/remote-device/templates/auth-success.js +0 -30
  104. package/dist/setup.log +0 -275
  105. package/dist/test-docx.d.ts +0 -1
  106. package/dist/test-setup.js +0 -14
  107. package/dist/tools/docx/builders/html-builder.d.ts +0 -17
  108. package/dist/tools/docx/builders/html-builder.js +0 -92
  109. package/dist/tools/docx/builders/image.d.ts +0 -14
  110. package/dist/tools/docx/builders/image.js +0 -84
  111. package/dist/tools/docx/builders/index.d.ts +0 -11
  112. package/dist/tools/docx/builders/index.js +0 -11
  113. package/dist/tools/docx/builders/markdown-builder.d.ts +0 -2
  114. package/dist/tools/docx/builders/markdown-builder.js +0 -260
  115. package/dist/tools/docx/builders/paragraph.d.ts +0 -12
  116. package/dist/tools/docx/builders/paragraph.js +0 -29
  117. package/dist/tools/docx/builders/table.d.ts +0 -10
  118. package/dist/tools/docx/builders/table.js +0 -138
  119. package/dist/tools/docx/builders/utils.d.ts +0 -5
  120. package/dist/tools/docx/builders/utils.js +0 -18
  121. package/dist/tools/docx/constants.d.ts +0 -32
  122. package/dist/tools/docx/constants.js +0 -61
  123. package/dist/tools/docx/converters/markdown-to-html.d.ts +0 -17
  124. package/dist/tools/docx/converters/markdown-to-html.js +0 -111
  125. package/dist/tools/docx/create.d.ts +0 -21
  126. package/dist/tools/docx/create.js +0 -386
  127. package/dist/tools/docx/dom.d.ts +0 -139
  128. package/dist/tools/docx/dom.js +0 -448
  129. package/dist/tools/docx/errors.d.ts +0 -28
  130. package/dist/tools/docx/errors.js +0 -48
  131. package/dist/tools/docx/extractors/images.d.ts +0 -14
  132. package/dist/tools/docx/extractors/images.js +0 -40
  133. package/dist/tools/docx/extractors/metadata.d.ts +0 -14
  134. package/dist/tools/docx/extractors/metadata.js +0 -64
  135. package/dist/tools/docx/extractors/sections.d.ts +0 -14
  136. package/dist/tools/docx/extractors/sections.js +0 -61
  137. package/dist/tools/docx/html.d.ts +0 -17
  138. package/dist/tools/docx/html.js +0 -111
  139. package/dist/tools/docx/index.d.ts +0 -10
  140. package/dist/tools/docx/index.js +0 -10
  141. package/dist/tools/docx/markdown.d.ts +0 -84
  142. package/dist/tools/docx/markdown.js +0 -507
  143. package/dist/tools/docx/modify.d.ts +0 -28
  144. package/dist/tools/docx/modify.js +0 -271
  145. package/dist/tools/docx/operations/handlers/index.d.ts +0 -39
  146. package/dist/tools/docx/operations/handlers/index.js +0 -152
  147. package/dist/tools/docx/operations/html-manipulator.d.ts +0 -24
  148. package/dist/tools/docx/operations/html-manipulator.js +0 -352
  149. package/dist/tools/docx/operations/index.d.ts +0 -14
  150. package/dist/tools/docx/operations/index.js +0 -61
  151. package/dist/tools/docx/operations/operation-handlers.d.ts +0 -3
  152. package/dist/tools/docx/operations/operation-handlers.js +0 -67
  153. package/dist/tools/docx/operations/preprocessor.d.ts +0 -14
  154. package/dist/tools/docx/operations/preprocessor.js +0 -44
  155. package/dist/tools/docx/operations/xml-replacer.d.ts +0 -9
  156. package/dist/tools/docx/operations/xml-replacer.js +0 -35
  157. package/dist/tools/docx/operations.d.ts +0 -13
  158. package/dist/tools/docx/operations.js +0 -13
  159. package/dist/tools/docx/ops/delete-paragraph-at-body-index.d.ts +0 -11
  160. package/dist/tools/docx/ops/delete-paragraph-at-body-index.js +0 -23
  161. package/dist/tools/docx/ops/header-replace-text-exact.d.ts +0 -13
  162. package/dist/tools/docx/ops/header-replace-text-exact.js +0 -55
  163. package/dist/tools/docx/ops/index.d.ts +0 -17
  164. package/dist/tools/docx/ops/index.js +0 -70
  165. package/dist/tools/docx/ops/insert-image-after-text.d.ts +0 -24
  166. package/dist/tools/docx/ops/insert-image-after-text.js +0 -128
  167. package/dist/tools/docx/ops/insert-paragraph-after-text.d.ts +0 -12
  168. package/dist/tools/docx/ops/insert-paragraph-after-text.js +0 -74
  169. package/dist/tools/docx/ops/insert-table-after-text.d.ts +0 -19
  170. package/dist/tools/docx/ops/insert-table-after-text.js +0 -57
  171. package/dist/tools/docx/ops/replace-hyperlink-url.d.ts +0 -12
  172. package/dist/tools/docx/ops/replace-hyperlink-url.js +0 -37
  173. package/dist/tools/docx/ops/replace-paragraph-at-body-index.d.ts +0 -9
  174. package/dist/tools/docx/ops/replace-paragraph-at-body-index.js +0 -25
  175. package/dist/tools/docx/ops/replace-paragraph-text-exact.d.ts +0 -21
  176. package/dist/tools/docx/ops/replace-paragraph-text-exact.js +0 -36
  177. package/dist/tools/docx/ops/replace-table-cell-text.d.ts +0 -25
  178. package/dist/tools/docx/ops/replace-table-cell-text.js +0 -85
  179. package/dist/tools/docx/ops/set-color-for-paragraph-exact.d.ts +0 -9
  180. package/dist/tools/docx/ops/set-color-for-paragraph-exact.js +0 -24
  181. package/dist/tools/docx/ops/set-color-for-style.d.ts +0 -13
  182. package/dist/tools/docx/ops/set-color-for-style.js +0 -31
  183. package/dist/tools/docx/ops/set-paragraph-style-at-body-index.d.ts +0 -8
  184. package/dist/tools/docx/ops/set-paragraph-style-at-body-index.js +0 -57
  185. package/dist/tools/docx/ops/table-set-cell-text.d.ts +0 -9
  186. package/dist/tools/docx/ops/table-set-cell-text.js +0 -40
  187. package/dist/tools/docx/parsers/image-extractor.d.ts +0 -18
  188. package/dist/tools/docx/parsers/image-extractor.js +0 -61
  189. package/dist/tools/docx/parsers/index.d.ts +0 -9
  190. package/dist/tools/docx/parsers/index.js +0 -9
  191. package/dist/tools/docx/parsers/paragraph-parser.d.ts +0 -2
  192. package/dist/tools/docx/parsers/paragraph-parser.js +0 -88
  193. package/dist/tools/docx/parsers/table-parser.d.ts +0 -9
  194. package/dist/tools/docx/parsers/table-parser.js +0 -72
  195. package/dist/tools/docx/parsers/xml-parser.d.ts +0 -25
  196. package/dist/tools/docx/parsers/xml-parser.js +0 -71
  197. package/dist/tools/docx/parsers/zip-reader.d.ts +0 -23
  198. package/dist/tools/docx/parsers/zip-reader.js +0 -52
  199. package/dist/tools/docx/read.d.ts +0 -27
  200. package/dist/tools/docx/read.js +0 -308
  201. package/dist/tools/docx/relationships.d.ts +0 -22
  202. package/dist/tools/docx/relationships.js +0 -76
  203. package/dist/tools/docx/structure.d.ts +0 -25
  204. package/dist/tools/docx/structure.js +0 -102
  205. package/dist/tools/docx/styled-html-parser.d.ts +0 -23
  206. package/dist/tools/docx/styled-html-parser.js +0 -1262
  207. package/dist/tools/docx/types.d.ts +0 -213
  208. package/dist/tools/docx/types.js +0 -5
  209. package/dist/tools/docx/utils/escaping.d.ts +0 -13
  210. package/dist/tools/docx/utils/escaping.js +0 -26
  211. package/dist/tools/docx/utils/images.d.ts +0 -9
  212. package/dist/tools/docx/utils/images.js +0 -26
  213. package/dist/tools/docx/utils/index.d.ts +0 -12
  214. package/dist/tools/docx/utils/index.js +0 -17
  215. package/dist/tools/docx/utils/markdown.d.ts +0 -13
  216. package/dist/tools/docx/utils/markdown.js +0 -32
  217. package/dist/tools/docx/utils/paths.d.ts +0 -15
  218. package/dist/tools/docx/utils/paths.js +0 -27
  219. package/dist/tools/docx/utils/versioning.d.ts +0 -25
  220. package/dist/tools/docx/utils/versioning.js +0 -55
  221. package/dist/tools/docx/utils.d.ts +0 -101
  222. package/dist/tools/docx/utils.js +0 -299
  223. package/dist/tools/docx/validate.d.ts +0 -33
  224. package/dist/tools/docx/validate.js +0 -49
  225. package/dist/tools/docx/validators.d.ts +0 -13
  226. package/dist/tools/docx/validators.js +0 -40
  227. package/dist/tools/docx/write.d.ts +0 -17
  228. package/dist/tools/docx/write.js +0 -88
  229. package/dist/tools/docx/xml-view-test.d.ts +0 -1
  230. package/dist/tools/docx/xml-view-test.js +0 -63
  231. package/dist/tools/docx/xml-view.d.ts +0 -56
  232. package/dist/tools/docx/xml-view.js +0 -169
  233. package/dist/tools/docx/zip.d.ts +0 -21
  234. package/dist/tools/docx/zip.js +0 -35
  235. package/dist/tools/macos-control/ax-adapter.d.ts +0 -55
  236. package/dist/tools/macos-control/ax-adapter.js +0 -438
  237. package/dist/tools/macos-control/cdp-adapter.d.ts +0 -23
  238. package/dist/tools/macos-control/cdp-adapter.js +0 -402
  239. package/dist/tools/macos-control/orchestrator.d.ts +0 -77
  240. package/dist/tools/macos-control/orchestrator.js +0 -136
  241. package/dist/tools/macos-control/role-aliases.d.ts +0 -5
  242. package/dist/tools/macos-control/role-aliases.js +0 -34
  243. package/dist/tools/macos-control/types.d.ts +0 -129
  244. package/dist/tools/macos-control/types.js +0 -1
  245. package/dist/tools/pdf-processor.d.ts +0 -1
  246. package/dist/tools/pdf-processor.js +0 -3
  247. package/dist/tools/search.d.ts +0 -32
  248. package/dist/tools/search.js +0 -202
  249. package/dist/ui/file-preview/src/components/toolbar.d.ts +0 -6
  250. package/dist/ui/file-preview/src/components/toolbar.js +0 -75
  251. package/dist/ui/shared/host-lifecycle.d.ts +0 -16
  252. package/dist/ui/shared/host-lifecycle.js +0 -35
  253. package/dist/ui/shared/rpc-client.d.ts +0 -14
  254. package/dist/ui/shared/rpc-client.js +0 -72
  255. package/dist/ui/shared/theme-adaptation.d.ts +0 -10
  256. package/dist/ui/shared/theme-adaptation.js +0 -118
  257. package/dist/ui/shared/tool-header.d.ts +0 -9
  258. package/dist/ui/shared/tool-header.js +0 -25
  259. package/dist/utils/crash-logger.d.ts +0 -18
  260. package/dist/utils/crash-logger.js +0 -44
  261. package/dist/utils/dedent.d.ts +0 -8
  262. package/dist/utils/dedent.js +0 -38
  263. /package/dist/{http-server-auto-tunnel.d.ts → ui/file-preview/src/model.js} +0 -0
@@ -1,377 +0,0 @@
1
- import { Router } from 'express';
2
- export function createOAuthRoutes(oauthManager, baseUrl) {
3
- const router = Router();
4
- // ==================== DISCOVERY ENDPOINTS ====================
5
- /**
6
- * OAuth Authorization Server Metadata
7
- * https://tools.ietf.org/html/rfc8414
8
- */
9
- router.get('/.well-known/oauth-authorization-server', (req, res) => {
10
- res.json({
11
- issuer: baseUrl,
12
- authorization_endpoint: `${baseUrl}/authorize`,
13
- token_endpoint: `${baseUrl}/token`,
14
- registration_endpoint: `${baseUrl}/register`,
15
- response_types_supported: ['code'],
16
- grant_types_supported: ['authorization_code'],
17
- code_challenge_methods_supported: ['S256'],
18
- token_endpoint_auth_methods_supported: ['none'],
19
- scopes_supported: ['mcp:tools']
20
- });
21
- });
22
- /**
23
- * MCP-specific OAuth Authorization Server Metadata
24
- * ChatGPT requires this endpoint with pre-registered client_id
25
- */
26
- router.get('/.well-known/oauth-authorization-server/mcp', (req, res) => {
27
- res.json({
28
- issuer: baseUrl,
29
- authorization_endpoint: `${baseUrl}/authorize`,
30
- token_endpoint: `${baseUrl}/token`,
31
- registration_endpoint: `${baseUrl}/register`,
32
- response_types_supported: ['code'],
33
- grant_types_supported: ['authorization_code'],
34
- code_challenge_methods_supported: ['S256'],
35
- token_endpoint_auth_methods_supported: ['none'],
36
- scopes_supported: ['mcp:tools'],
37
- // MCP-specific: Pre-registered client for ChatGPT
38
- mcp: {
39
- client_id: 'chatgpt-fixed-client-id',
40
- redirect_uri: `${baseUrl}/callback`
41
- }
42
- });
43
- });
44
- /**
45
- * OAuth Protected Resource Metadata
46
- * https://tools.ietf.org/html/rfc8707
47
- */
48
- router.get('/.well-known/oauth-protected-resource', (req, res) => {
49
- res.json({
50
- resource: baseUrl,
51
- authorization_servers: [baseUrl],
52
- scopes_supported: ['mcp:tools'],
53
- bearer_methods_supported: ['header']
54
- });
55
- });
56
- /**
57
- * MCP-specific OAuth Protected Resource Metadata
58
- * ChatGPT queries this variant
59
- */
60
- router.get('/.well-known/oauth-protected-resource/mcp', (req, res) => {
61
- res.json({
62
- resource: baseUrl,
63
- authorization_servers: [baseUrl],
64
- scopes_supported: ['mcp:tools'],
65
- bearer_methods_supported: ['header']
66
- });
67
- });
68
- // ==================== CLIENT REGISTRATION ====================
69
- /**
70
- * Dynamic Client Registration
71
- * https://tools.ietf.org/html/rfc7591
72
- */
73
- router.post('/register', (req, res) => {
74
- const { redirect_uris, client_name } = req.body;
75
- console.log(`\n🔐 CLIENT REGISTRATION`);
76
- console.log(` Client Name: ${client_name || 'Unnamed'}`);
77
- console.log(` Redirect URIs:`, redirect_uris);
78
- if (!redirect_uris || !Array.isArray(redirect_uris) || redirect_uris.length === 0) {
79
- return res.status(400).json({
80
- error: 'invalid_redirect_uri',
81
- error_description: 'redirect_uris must be a non-empty array'
82
- });
83
- }
84
- // Check if this looks like ChatGPT
85
- const isChatGPT = redirect_uris.some(uri => uri.includes('chatgpt.com') || uri.includes('openai.com'));
86
- // Check if this looks like Claude
87
- const isClaude = redirect_uris.some(uri => uri.includes('claude.ai') || uri.includes('anthropic.com'));
88
- let client;
89
- if (isChatGPT) {
90
- // Return pre-registered ChatGPT client
91
- client = oauthManager.getClient('chatgpt-fixed-client-id');
92
- console.log(`✅ Using pre-registered ChatGPT client`);
93
- // Add any new redirect URIs they're using
94
- redirect_uris.forEach(uri => {
95
- if (!client.redirect_uris.includes(uri)) {
96
- client.redirect_uris.push(uri);
97
- console.log(` 📝 Added redirect_uri: ${uri}`);
98
- }
99
- });
100
- }
101
- else if (isClaude) {
102
- // Return pre-registered Claude client
103
- client = oauthManager.getClient('claude-fixed-client-id');
104
- console.log(`✅ Using pre-registered Claude client`);
105
- // Add any new redirect URIs they're using
106
- redirect_uris.forEach(uri => {
107
- if (!client.redirect_uris.includes(uri)) {
108
- client.redirect_uris.push(uri);
109
- console.log(` 📝 Added redirect_uri: ${uri}`);
110
- }
111
- });
112
- }
113
- else {
114
- // Register new client for other tools
115
- client = oauthManager.registerClient(redirect_uris, client_name);
116
- console.log(`✅ Registered new client: ${client.client_id}`);
117
- }
118
- res.status(201).json({
119
- client_id: client.client_id,
120
- client_name: client.client_name,
121
- redirect_uris: client.redirect_uris,
122
- grant_types: client.grant_types,
123
- response_types: client.response_types,
124
- token_endpoint_auth_method: 'none'
125
- });
126
- });
127
- // ==================== AUTHORIZATION ====================
128
- /**
129
- * Authorization Endpoint (GET) - Display login page
130
- */
131
- router.get('/authorize', (req, res) => {
132
- const { client_id, redirect_uri, response_type, state, code_challenge, code_challenge_method, scope } = req.query;
133
- console.log(`\n🔐 AUTHORIZATION REQUEST`);
134
- console.log(` Client ID: ${client_id}`);
135
- console.log(` Redirect URI: ${redirect_uri}`);
136
- console.log(` Response Type: ${response_type}`);
137
- console.log(` State: ${state}`);
138
- console.log(` Code Challenge: ${code_challenge ? 'present' : 'missing'}`);
139
- console.log(` Scope: ${scope}`);
140
- // Validate client
141
- const client = oauthManager.getClient(client_id);
142
- if (!client) {
143
- console.log(`❌ Client ${client_id} not found. Was /register called?`);
144
- console.log(` Registered clients: ${oauthManager.listClients()}`);
145
- return res.status(400).send(`
146
- <html>
147
- <head><title>Error</title></head>
148
- <body style="font-family: system-ui; max-width: 400px; margin: 50px auto; padding: 20px;">
149
- <h2>❌ Invalid Client</h2>
150
- <p>The client_id <code>${client_id}</code> is not recognized.</p>
151
- <p><small>The client must register at <code>/register</code> first.</small></p>
152
- </body>
153
- </html>
154
- `);
155
- }
156
- console.log(`✅ Client validated: ${client.client_name}`);
157
- // Validate redirect_uri
158
- if (!client.redirect_uris.includes(redirect_uri)) {
159
- console.log(`❌ Invalid redirect_uri: ${redirect_uri}`);
160
- console.log(` Registered URIs:`, client.redirect_uris);
161
- return res.status(400).send(`
162
- <html>
163
- <head><title>Error</title></head>
164
- <body style="font-family: system-ui; max-width: 400px; margin: 50px auto; padding: 20px;">
165
- <h2>❌ Invalid Redirect URI</h2>
166
- <p>The redirect_uri <code>${redirect_uri}</code> is not registered for this client.</p>
167
- <p><strong>Registered URIs for ${client.client_name}:</strong></p>
168
- <ul>
169
- ${client.redirect_uris.map(uri => `<li><code>${uri}</code></li>`).join('')}
170
- </ul>
171
- </body>
172
- </html>
173
- `);
174
- }
175
- // Display login page
176
- res.send(`
177
- <html>
178
- <head>
179
- <title>Desktop Commander - Login</title>
180
- <style>
181
- body {
182
- font-family: system-ui, -apple-system, sans-serif;
183
- max-width: 400px;
184
- margin: 50px auto;
185
- padding: 20px;
186
- background: #f5f5f5;
187
- }
188
- .container {
189
- background: white;
190
- padding: 30px;
191
- border-radius: 10px;
192
- box-shadow: 0 2px 10px rgba(0,0,0,0.1);
193
- }
194
- h2 {
195
- margin-top: 0;
196
- color: #333;
197
- }
198
- .info {
199
- background: #f0f0f0;
200
- padding: 15px;
201
- margin: 20px 0;
202
- border-radius: 5px;
203
- font-size: 14px;
204
- }
205
- input {
206
- width: 100%;
207
- padding: 12px;
208
- margin: 10px 0;
209
- box-sizing: border-box;
210
- border: 1px solid #ddd;
211
- border-radius: 5px;
212
- font-size: 16px;
213
- }
214
- button {
215
- width: 100%;
216
- padding: 14px;
217
- background: #0066cc;
218
- color: white;
219
- border: none;
220
- border-radius: 5px;
221
- cursor: pointer;
222
- font-size: 16px;
223
- font-weight: 600;
224
- }
225
- button:hover {
226
- background: #0052a3;
227
- }
228
- .demo-creds {
229
- text-align: center;
230
- color: #666;
231
- margin-top: 20px;
232
- font-size: 14px;
233
- }
234
- </style>
235
- </head>
236
- <body>
237
- <div class="container">
238
- <h2>🔐 Login to Desktop Commander</h2>
239
- <div class="info">
240
- <strong>Client:</strong> ${client.client_name}
241
- </div>
242
- <form method="POST" action="/authorize">
243
- <input type="hidden" name="client_id" value="${client_id}">
244
- <input type="hidden" name="redirect_uri" value="${redirect_uri}">
245
- <input type="hidden" name="response_type" value="${response_type}">
246
- <input type="hidden" name="state" value="${state || ''}">
247
- <input type="hidden" name="code_challenge" value="${code_challenge || ''}">
248
- <input type="hidden" name="code_challenge_method" value="${code_challenge_method || ''}">
249
- <input type="hidden" name="scope" value="${scope || 'mcp:tools'}">
250
-
251
- <input type="text" name="username" placeholder="Username" required autofocus>
252
- <input type="password" name="password" placeholder="Password" required>
253
-
254
- <button type="submit">Login & Authorize</button>
255
- </form>
256
- <div class="demo-creds">
257
- Demo credentials:<br>
258
- <strong>admin</strong> / <strong>password123</strong>
259
- </div>
260
- </div>
261
- </body>
262
- </html>
263
- `);
264
- });
265
- /**
266
- * Authorization Endpoint (POST) - Process login
267
- */
268
- router.post('/authorize', (req, res) => {
269
- const { username, password, client_id, redirect_uri, state, code_challenge, code_challenge_method, scope } = req.body;
270
- console.log(`\n🔐 PROCESSING LOGIN`);
271
- console.log(` Username: ${username}`);
272
- console.log(` Client ID: ${client_id}`);
273
- // Validate credentials
274
- if (!oauthManager.validateUser(username, password)) {
275
- return res.send(`
276
- <html>
277
- <head><title>Login Failed</title></head>
278
- <body style="font-family: system-ui; max-width: 400px; margin: 50px auto; padding: 20px;">
279
- <h2>❌ Invalid Credentials</h2>
280
- <p>The username or password is incorrect.</p>
281
- <a href="/authorize?client_id=${client_id}&redirect_uri=${encodeURIComponent(redirect_uri)}&response_type=code&state=${state || ''}&code_challenge=${code_challenge || ''}&code_challenge_method=${code_challenge_method || ''}&scope=${scope || 'mcp:tools'}">Try Again</a>
282
- </body>
283
- </html>
284
- `);
285
- }
286
- // Create authorization code
287
- const code = oauthManager.createAuthCode({
288
- username,
289
- client_id,
290
- redirect_uri,
291
- code_challenge,
292
- code_challenge_method,
293
- scope: scope || 'mcp:tools'
294
- });
295
- console.log(`✅ User ${username} authorized, redirecting...`);
296
- // Redirect back to client with authorization code
297
- const redirectUrl = new URL(redirect_uri);
298
- redirectUrl.searchParams.set('code', code);
299
- if (state) {
300
- redirectUrl.searchParams.set('state', state);
301
- }
302
- res.redirect(redirectUrl.toString());
303
- });
304
- // ==================== TOKEN ENDPOINT ====================
305
- /**
306
- * Callback endpoint - for compatibility with MCP discovery
307
- * This redirects to the client's actual redirect_uri with the code
308
- */
309
- router.get('/callback', (req, res) => {
310
- const { code, state, error, error_description } = req.query;
311
- console.log(`\n🔄 CALLBACK`);
312
- console.log(` Code: ${code ? 'present' : 'missing'}`);
313
- console.log(` State: ${state}`);
314
- if (error) {
315
- return res.send(`
316
- <html>
317
- <head><title>OAuth Error</title></head>
318
- <body style="font-family: system-ui; max-width: 400px; margin: 50px auto; padding: 20px;">
319
- <h2>❌ OAuth Error</h2>
320
- <p><strong>Error:</strong> ${error}</p>
321
- <p><strong>Description:</strong> ${error_description || 'No description provided'}</p>
322
- </body>
323
- </html>
324
- `);
325
- }
326
- // This endpoint shouldn't really be called directly
327
- // It's here for compatibility with the MCP discovery document
328
- res.send(`
329
- <html>
330
- <head><title>OAuth Callback</title></head>
331
- <body style="font-family: system-ui; max-width: 400px; margin: 50px auto; padding: 20px;">
332
- <h2>✅ Authorization Successful</h2>
333
- <p>You can close this window and return to the application.</p>
334
- </body>
335
- </html>
336
- `);
337
- });
338
- /**
339
- * Token Endpoint - Exchange authorization code for access token
340
- */
341
- router.post('/token', (req, res) => {
342
- const { grant_type, code, redirect_uri, client_id, code_verifier } = req.body;
343
- console.log(`\n🎫 TOKEN REQUEST`);
344
- console.log(` Grant Type: ${grant_type}`);
345
- console.log(` Client ID: ${client_id}`);
346
- // Validate grant type
347
- if (grant_type !== 'authorization_code') {
348
- return res.status(400).json({
349
- error: 'unsupported_grant_type',
350
- error_description: 'Only authorization_code grant type is supported'
351
- });
352
- }
353
- // Validate authorization code
354
- const validation = oauthManager.validateAuthCode(code, client_id, redirect_uri, code_verifier);
355
- if (!validation.valid) {
356
- console.log(`❌ Token request failed: ${validation.error}`);
357
- return res.status(400).json({
358
- error: 'invalid_grant',
359
- error_description: validation.error
360
- });
361
- }
362
- // Create access token
363
- const accessToken = oauthManager.createJWT({
364
- sub: validation.data.username,
365
- client_id: validation.data.client_id,
366
- scope: validation.data.scope
367
- });
368
- console.log(`✅ Issued token for ${validation.data.username}`);
369
- res.json({
370
- access_token: accessToken,
371
- token_type: 'Bearer',
372
- expires_in: 3600,
373
- scope: validation.data.scope
374
- });
375
- });
376
- return router;
377
- }
@@ -1,22 +0,0 @@
1
- import type { OAuthConfig, AuthorizationServerMetadata, TokenResponse, AccessToken, AuthorizationRequest, TokenRequest } from './types.js';
2
- export declare class OAuthProvider {
3
- private config;
4
- private users;
5
- private authCodes;
6
- private accessTokens;
7
- constructor(config: OAuthConfig);
8
- static generatePKCE(): {
9
- codeVerifier: string;
10
- codeChallenge: string;
11
- };
12
- getAuthorizationServerMetadata(): AuthorizationServerMetadata;
13
- handleAuthorizationRequest(params: AuthorizationRequest): {
14
- authUrl: string;
15
- authCode?: string;
16
- error?: string;
17
- };
18
- handleTokenRequest(params: TokenRequest): Promise<TokenResponse | {
19
- error: string;
20
- }>;
21
- validateAccessToken(token: string): AccessToken | null;
22
- }
@@ -1,124 +0,0 @@
1
- import crypto from 'crypto';
2
- export class OAuthProvider {
3
- constructor(config) {
4
- this.users = new Map();
5
- this.authCodes = new Map();
6
- this.accessTokens = new Map();
7
- this.config = config;
8
- // Add a default user for testing
9
- this.users.set('admin', {
10
- email: 'admin@localhost',
11
- password: 'admin123' // In production, hash this!
12
- });
13
- }
14
- // Generate PKCE code verifier and challenge
15
- static generatePKCE() {
16
- const codeVerifier = crypto.randomBytes(32).toString('base64url');
17
- const codeChallenge = crypto
18
- .createHash('sha256')
19
- .update(codeVerifier)
20
- .digest('base64url');
21
- return { codeVerifier, codeChallenge };
22
- }
23
- // Get Authorization Server Metadata (required by MCP spec)
24
- getAuthorizationServerMetadata() {
25
- const baseUrl = this.config.issuer;
26
- return {
27
- issuer: baseUrl,
28
- authorization_endpoint: `${baseUrl}/authorize`,
29
- token_endpoint: `${baseUrl}/token`,
30
- registration_endpoint: `${baseUrl}/register`,
31
- revocation_endpoint: `${baseUrl}/revoke`,
32
- jwks_uri: `${baseUrl}/.well-known/jwks.json`,
33
- response_types_supported: ['code'],
34
- grant_types_supported: ['authorization_code', 'refresh_token'],
35
- token_endpoint_auth_methods_supported: ['none', 'client_secret_basic'],
36
- code_challenge_methods_supported: ['S256'],
37
- scopes_supported: ['mcp:access', 'mcp:tools', 'mcp:resources']
38
- };
39
- }
40
- // Handle authorization request
41
- handleAuthorizationRequest(params) {
42
- if (!params.client_id || !params.redirect_uri || !params.code_challenge) {
43
- return { authUrl: '', error: 'Missing required parameters' };
44
- }
45
- if (params.code_challenge_method !== 'S256') {
46
- return { authUrl: '', error: 'Unsupported code_challenge_method' };
47
- }
48
- // Generate authorization code
49
- const authCode = crypto.randomBytes(32).toString('hex');
50
- const expiresAt = Date.now() + 10 * 60 * 1000; // 10 minutes
51
- // Store authorization code
52
- this.authCodes.set(authCode, {
53
- userId: 'admin', // For simplicity, auto-approve for admin user
54
- clientId: params.client_id,
55
- redirectUri: params.redirect_uri,
56
- scope: params.scope || 'mcp:access',
57
- codeChallenge: params.code_challenge,
58
- codeChallengeMethod: params.code_challenge_method,
59
- expiresAt
60
- });
61
- // Build redirect URL with auth code
62
- const redirectUrl = new URL(params.redirect_uri);
63
- redirectUrl.searchParams.set('code', authCode);
64
- if (params.state) {
65
- redirectUrl.searchParams.set('state', params.state);
66
- }
67
- return { authUrl: redirectUrl.toString(), authCode };
68
- }
69
- // Exchange authorization code for access token
70
- async handleTokenRequest(params) {
71
- const authCodeData = this.authCodes.get(params.code);
72
- if (!authCodeData) {
73
- return { error: 'Invalid authorization code' };
74
- }
75
- if (Date.now() > authCodeData.expiresAt) {
76
- this.authCodes.delete(params.code);
77
- return { error: 'Authorization code expired' };
78
- }
79
- // Verify PKCE
80
- const computedChallenge = crypto
81
- .createHash('sha256')
82
- .update(params.code_verifier)
83
- .digest('base64url');
84
- if (computedChallenge !== authCodeData.codeChallenge) {
85
- return { error: 'Invalid code_verifier' };
86
- }
87
- // Verify client and redirect URI
88
- if (params.client_id !== authCodeData.clientId ||
89
- params.redirect_uri !== authCodeData.redirectUri) {
90
- return { error: 'Invalid client_id or redirect_uri' };
91
- }
92
- // Generate access token
93
- const accessToken = crypto.randomBytes(32).toString('hex');
94
- const expiresIn = 3600; // 1 hour
95
- const tokenData = {
96
- sub: authCodeData.userId,
97
- aud: params.client_id,
98
- iss: this.config.issuer,
99
- exp: Math.floor(Date.now() / 1000) + expiresIn,
100
- iat: Math.floor(Date.now() / 1000),
101
- scope: authCodeData.scope
102
- };
103
- this.accessTokens.set(accessToken, tokenData);
104
- this.authCodes.delete(params.code);
105
- return {
106
- access_token: accessToken,
107
- token_type: 'Bearer',
108
- expires_in: expiresIn,
109
- scope: authCodeData.scope
110
- };
111
- }
112
- // Validate access token
113
- validateAccessToken(token) {
114
- const tokenData = this.accessTokens.get(token);
115
- if (!tokenData) {
116
- return null;
117
- }
118
- if (Date.now() / 1000 > tokenData.exp) {
119
- this.accessTokens.delete(token);
120
- return null;
121
- }
122
- return tokenData;
123
- }
124
- }
@@ -1,18 +0,0 @@
1
- import http from 'http';
2
- import type { OAuthConfig } from './types.js';
3
- export declare class OAuthHttpServer {
4
- private server;
5
- private oauthProvider;
6
- private mcpHandler;
7
- constructor(config: OAuthConfig, mcpHandler: (req: http.IncomingMessage, res: http.ServerResponse) => void);
8
- private handleRequest;
9
- private setCorsHeaders;
10
- private handleAuthServerMetadata;
11
- private handleAuthorize;
12
- private handleToken;
13
- private handleCallback;
14
- private sendUnauthorized;
15
- private getRequestBody;
16
- listen(port: number, callback?: () => void): void;
17
- close(callback?: () => void): void;
18
- }