@nones/dsh-session-mcp 1.0.2 → 1.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 +22 -7
- package/dist/client.d.ts +0 -0
- package/dist/client.js +198 -0
- package/dist/config.d.ts +28 -0
- package/dist/config.js +21 -0
- package/dist/index.js +26 -1
- package/dist/types.d.ts +16 -0
- package/package.json +15 -4
package/README.md
CHANGED
|
@@ -49,11 +49,18 @@ Restart the harness (or reload the profile) and the endpoint starts with it.
|
|
|
49
49
|
|
|
50
50
|
## Get your config
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
Open **Settings → MCP** in the harness. The page shows the live endpoint, the bearer
|
|
53
|
+
token (masked until you reveal it), and three copy-ready blocks:
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
| Block | For |
|
|
56
|
+
|---|---|
|
|
57
|
+
| JSON — `mcpServers` | Claude Desktop, Cursor, and any JSON-configured client |
|
|
58
|
+
| Codex — `~/.codex/config.toml` | Codex CLI / IDE |
|
|
59
|
+
| Claude Code — CLI | One `claude mcp add …` command |
|
|
60
|
+
|
|
61
|
+
Each block has its own **Copy** button; the endpoint and the token have one too.
|
|
62
|
+
|
|
63
|
+
The same data is on disk at `$DSH_HOME/state/dsh-session-mcp.json`:
|
|
57
64
|
|
|
58
65
|
```json
|
|
59
66
|
{
|
|
@@ -71,7 +78,7 @@ $DSH_HOME/state/dsh-session-mcp.json
|
|
|
71
78
|
}
|
|
72
79
|
```
|
|
73
80
|
|
|
74
|
-
|
|
81
|
+
Per client:
|
|
75
82
|
|
|
76
83
|
**Claude Code**
|
|
77
84
|
|
|
@@ -144,12 +151,20 @@ Written in TypeScript, compiled to `dist/` (committed, so installs need no build
|
|
|
144
151
|
|
|
145
152
|
| Source | Role |
|
|
146
153
|
|---|---|
|
|
147
|
-
| `src/index.ts` | Cordis plugin: reads/creates the bearer, starts the listener, publishes the state file, closes the listener on unload |
|
|
154
|
+
| `src/index.ts` | Cordis plugin: reads/creates the bearer, starts the listener, publishes the state file, serves the Settings config route, closes the listener on unload |
|
|
148
155
|
| `src/server.ts` | `node:http` listener with the bearer gate in front of the official SDK's `createMcpHandler` + `toNodeHandler` |
|
|
149
156
|
| `src/tools.ts` | The five tools, backed directly by `ctx.sessionController` |
|
|
150
|
-
| `src/config.ts` | Token persistence, constant-time bearer comparison, client
|
|
157
|
+
| `src/config.ts` | Token persistence, constant-time bearer comparison, client snippets |
|
|
158
|
+
| `src/client.ts` | The **Settings → MCP** page (classic script for `window.__ModuleLoader__`) |
|
|
151
159
|
| `src/types.ts` | The narrow structural slice of Harness types this package needs |
|
|
152
160
|
|
|
161
|
+
The Settings page reads `/api/dsh-session-mcp/config` over the authenticated browser
|
|
162
|
+
channel, so the token never enters the served HTML.
|
|
163
|
+
|
|
164
|
+
> **After installing**, restart the harness once: the browser module roster is composed
|
|
165
|
+
> from the packages present at boot, so a newly installed Client half appears on the next
|
|
166
|
+
> start.
|
|
167
|
+
|
|
153
168
|
## Development
|
|
154
169
|
|
|
155
170
|
```bash
|
package/dist/client.d.ts
ADDED
|
File without changes
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* dsh-session-mcp — Client half.
|
|
4
|
+
*
|
|
5
|
+
* Registers the MCP settings page: the live endpoint, the bearer token, and
|
|
6
|
+
* copy-ready configuration blocks for every client this harness can serve.
|
|
7
|
+
*
|
|
8
|
+
* The page reads the config over the authenticated `/api` channel, so the token
|
|
9
|
+
* never appears in the served HTML.
|
|
10
|
+
*
|
|
11
|
+
* This file is a classic script on purpose: the Web shell loads it through
|
|
12
|
+
* `window.__ModuleLoader__`, and React arrives from the browser module table.
|
|
13
|
+
* Every binding lives inside the factory so re-evaluating the script (HMR)
|
|
14
|
+
* cannot redeclare a global.
|
|
15
|
+
*
|
|
16
|
+
* @module dsh-session-mcp/client
|
|
17
|
+
*/
|
|
18
|
+
;
|
|
19
|
+
globalThis.__ModuleLoader__.load({
|
|
20
|
+
id: '@nones/dsh-session-mcp',
|
|
21
|
+
factory(require) {
|
|
22
|
+
const g = globalThis;
|
|
23
|
+
const React = require('react');
|
|
24
|
+
const h = React.createElement;
|
|
25
|
+
/** Locale namespace owned by this page. */
|
|
26
|
+
const NS = 'dsh-session-mcp';
|
|
27
|
+
/** Where the Host publishes the live config. */
|
|
28
|
+
const CONFIG_URL = '/api/dsh-session-mcp/config';
|
|
29
|
+
const EN = {
|
|
30
|
+
title: 'MCP',
|
|
31
|
+
heading: 'MCP endpoint',
|
|
32
|
+
description: 'Connect Claude Code, Codex, Cursor or any other MCP client to this harness. The endpoint starts together with the harness and requires the bearer token below.',
|
|
33
|
+
endpoint: 'Endpoint',
|
|
34
|
+
bearer: 'Bearer token',
|
|
35
|
+
show: 'Show',
|
|
36
|
+
hide: 'Hide',
|
|
37
|
+
copy: 'Copy',
|
|
38
|
+
copied: 'Copied',
|
|
39
|
+
jsonTitle: 'JSON — mcpServers',
|
|
40
|
+
codexTitle: 'Codex — ~/.codex/config.toml',
|
|
41
|
+
claudeTitle: 'Claude Code — CLI',
|
|
42
|
+
note: 'Paste any block into your client. The token is stable across restarts; it rotates only when you delete $DSH_HOME/state/dsh-session-mcp.json and restart the harness.',
|
|
43
|
+
loading: 'Loading…',
|
|
44
|
+
error: 'Could not read the endpoint config: ',
|
|
45
|
+
};
|
|
46
|
+
const RU = {
|
|
47
|
+
title: 'MCP',
|
|
48
|
+
heading: 'MCP-эндпоинт',
|
|
49
|
+
description: 'Подключите Claude Code, Codex, Cursor или любой другой MCP-клиент к этому харнесу. Эндпоинт поднимается вместе с харнесом и требует Bearer-токен ниже.',
|
|
50
|
+
endpoint: 'Эндпоинт',
|
|
51
|
+
bearer: 'Bearer-токен',
|
|
52
|
+
show: 'Показать',
|
|
53
|
+
hide: 'Скрыть',
|
|
54
|
+
copy: 'Копировать',
|
|
55
|
+
copied: 'Скопировано',
|
|
56
|
+
jsonTitle: 'JSON — mcpServers',
|
|
57
|
+
codexTitle: 'Codex — ~/.codex/config.toml',
|
|
58
|
+
claudeTitle: 'Claude Code — CLI',
|
|
59
|
+
note: 'Вставьте любой блок в свой клиент. Токен не меняется между перезапусками; он обновится только если удалить $DSH_HOME/state/dsh-session-mcp.json и перезапустить харнес.',
|
|
60
|
+
loading: 'Загрузка…',
|
|
61
|
+
error: 'Не удалось прочитать конфиг эндпоинта: ',
|
|
62
|
+
};
|
|
63
|
+
/** Theme-bound inline styles; no colors are hardcoded. */
|
|
64
|
+
const styles = {
|
|
65
|
+
page: {
|
|
66
|
+
display: 'grid',
|
|
67
|
+
gap: '16px',
|
|
68
|
+
maxWidth: '760px',
|
|
69
|
+
fontSize: '13px',
|
|
70
|
+
lineHeight: 1.5,
|
|
71
|
+
color: 'var(--dsw-alias-label-primary)',
|
|
72
|
+
},
|
|
73
|
+
heading: { margin: 0, fontSize: '16px', fontWeight: 600 },
|
|
74
|
+
description: { margin: 0, color: 'var(--dsw-alias-label-secondary)' },
|
|
75
|
+
card: {
|
|
76
|
+
display: 'grid',
|
|
77
|
+
gap: '10px',
|
|
78
|
+
padding: '14px 16px',
|
|
79
|
+
border: '1px solid var(--dsw-alias-border-l1)',
|
|
80
|
+
borderRadius: '12px',
|
|
81
|
+
background: 'var(--dsw-alias-bg-layer-1)',
|
|
82
|
+
},
|
|
83
|
+
cardHead: {
|
|
84
|
+
display: 'flex',
|
|
85
|
+
alignItems: 'center',
|
|
86
|
+
justifyContent: 'space-between',
|
|
87
|
+
gap: '12px',
|
|
88
|
+
},
|
|
89
|
+
cardTitle: { fontSize: '12px', fontWeight: 600, color: 'var(--dsw-alias-label-secondary)' },
|
|
90
|
+
row: {
|
|
91
|
+
display: 'flex',
|
|
92
|
+
alignItems: 'center',
|
|
93
|
+
justifyContent: 'space-between',
|
|
94
|
+
gap: '12px',
|
|
95
|
+
},
|
|
96
|
+
rowLabel: { color: 'var(--dsw-alias-label-secondary)', whiteSpace: 'nowrap' },
|
|
97
|
+
rowValue: {
|
|
98
|
+
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
|
|
99
|
+
fontSize: '12px',
|
|
100
|
+
wordBreak: 'break-all',
|
|
101
|
+
flex: '1 1 auto',
|
|
102
|
+
textAlign: 'right',
|
|
103
|
+
},
|
|
104
|
+
actions: { display: 'flex', gap: '6px', flex: '0 0 auto' },
|
|
105
|
+
button: {
|
|
106
|
+
font: 'inherit',
|
|
107
|
+
fontSize: '12px',
|
|
108
|
+
padding: '3px 10px',
|
|
109
|
+
borderRadius: '8px',
|
|
110
|
+
border: '1px solid var(--dsw-alias-border-l2)',
|
|
111
|
+
background: 'var(--dsw-alias-bg-layer-2)',
|
|
112
|
+
color: 'var(--dsw-alias-label-primary)',
|
|
113
|
+
cursor: 'pointer',
|
|
114
|
+
},
|
|
115
|
+
pre: {
|
|
116
|
+
margin: 0,
|
|
117
|
+
padding: '12px',
|
|
118
|
+
borderRadius: '8px',
|
|
119
|
+
background: 'var(--dsw-alias-bg-layer-2)',
|
|
120
|
+
border: '1px solid var(--dsw-alias-border-l1)',
|
|
121
|
+
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
|
|
122
|
+
fontSize: '12px',
|
|
123
|
+
lineHeight: 1.45,
|
|
124
|
+
overflow: 'auto',
|
|
125
|
+
maxHeight: '220px',
|
|
126
|
+
whiteSpace: 'pre',
|
|
127
|
+
},
|
|
128
|
+
note: { margin: 0, color: 'var(--dsw-alias-label-secondary)', fontSize: '12px' },
|
|
129
|
+
error: { margin: 0, color: 'var(--dsw-alias-state-error-primary)' },
|
|
130
|
+
};
|
|
131
|
+
return {
|
|
132
|
+
inject: ['slots', 'locale'],
|
|
133
|
+
apply(ctx) {
|
|
134
|
+
ctx.effect(() => ctx.locale.register(NS, 'en', EN));
|
|
135
|
+
ctx.effect(() => ctx.locale.register(NS, 'ru', RU));
|
|
136
|
+
const t = ctx.locale.bind(NS);
|
|
137
|
+
/** Re-render on locale switches so the page follows the active language. */
|
|
138
|
+
function useLocaleRevision() {
|
|
139
|
+
const [, bump] = React.useState(0);
|
|
140
|
+
React.useEffect(() => ctx.locale.subscribe(() => bump((n) => n + 1)), []);
|
|
141
|
+
}
|
|
142
|
+
function CopyButton(props) {
|
|
143
|
+
const [copied, setCopied] = React.useState(false);
|
|
144
|
+
const onCopy = React.useCallback(() => {
|
|
145
|
+
const clipboard = g.navigator?.clipboard;
|
|
146
|
+
if (clipboard === undefined)
|
|
147
|
+
return;
|
|
148
|
+
clipboard.writeText(props.text).then(() => {
|
|
149
|
+
setCopied(true);
|
|
150
|
+
g.setTimeout(() => setCopied(false), 1600);
|
|
151
|
+
}, () => undefined);
|
|
152
|
+
}, [props.text]);
|
|
153
|
+
return h('button', { type: 'button', style: styles.button, onClick: onCopy }, copied ? t('copied') : t('copy'));
|
|
154
|
+
}
|
|
155
|
+
function Snippet(props) {
|
|
156
|
+
return h('section', { style: styles.card }, h('div', { style: styles.cardHead }, h('span', { style: styles.cardTitle }, props.title), h(CopyButton, { text: props.text })), h('pre', { style: styles.pre }, props.text));
|
|
157
|
+
}
|
|
158
|
+
function Section() {
|
|
159
|
+
useLocaleRevision();
|
|
160
|
+
const [state, setState] = React.useState({ status: 'loading' });
|
|
161
|
+
const [revealed, setRevealed] = React.useState(false);
|
|
162
|
+
React.useEffect(() => {
|
|
163
|
+
let alive = true;
|
|
164
|
+
g.fetch(CONFIG_URL, { headers: { accept: 'application/json' }, credentials: 'same-origin' })
|
|
165
|
+
.then((response) => response.ok ? response.json() : Promise.reject(new Error(`HTTP ${String(response.status)}`)))
|
|
166
|
+
.then((data) => {
|
|
167
|
+
if (alive)
|
|
168
|
+
setState({ status: 'ready', data });
|
|
169
|
+
})
|
|
170
|
+
.catch((error) => {
|
|
171
|
+
if (alive)
|
|
172
|
+
setState({ status: 'error', message: String(error?.message ?? error) });
|
|
173
|
+
});
|
|
174
|
+
return () => {
|
|
175
|
+
alive = false;
|
|
176
|
+
};
|
|
177
|
+
}, []);
|
|
178
|
+
const header = h('div', { style: { display: 'grid', gap: '4px' } }, h('h2', { style: styles.heading }, t('heading')), h('p', { style: styles.description }, t('description')));
|
|
179
|
+
if (state.status === 'loading') {
|
|
180
|
+
return h('div', { style: styles.page }, header, h('p', { style: styles.note }, t('loading')));
|
|
181
|
+
}
|
|
182
|
+
if (state.status === 'error') {
|
|
183
|
+
return h('div', { style: styles.page }, header, h('p', { style: styles.error }, `${t('error')}${String(state.message)}`));
|
|
184
|
+
}
|
|
185
|
+
const data = state.data;
|
|
186
|
+
const token = String(data.token);
|
|
187
|
+
const masked = `${token.slice(0, 6)}…${token.slice(-4)}`;
|
|
188
|
+
return h('div', { style: styles.page }, header, h('section', { style: styles.card }, h('div', { style: styles.row }, h('span', { style: styles.rowLabel }, t('endpoint')), h('span', { style: styles.rowValue }, data.url), h('div', { style: styles.actions }, h(CopyButton, { text: data.url }))), h('div', { style: styles.row }, h('span', { style: styles.rowLabel }, t('bearer')), h('span', { style: styles.rowValue }, revealed ? token : masked), h('div', { style: styles.actions }, h('button', {
|
|
189
|
+
type: 'button',
|
|
190
|
+
style: styles.button,
|
|
191
|
+
onClick: () => setRevealed((value) => !value),
|
|
192
|
+
}, revealed ? t('hide') : t('show')), h(CopyButton, { text: token })))), h(Snippet, { title: t('jsonTitle'), text: data.snippets.json }), h(Snippet, { title: t('codexTitle'), text: data.snippets.codexToml }), h(Snippet, { title: t('claudeTitle'), text: data.snippets.claudeCode }), h('p', { style: styles.note }, t('note')));
|
|
193
|
+
}
|
|
194
|
+
ctx.slots.inject('settings.section', () => ctx.slots.register({ name: 'settings.section', id: NS, order: 30, label: () => t('title') }, Section));
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
},
|
|
198
|
+
});
|
package/dist/config.d.ts
CHANGED
|
@@ -75,3 +75,31 @@ export declare function bearerMatches(expected: string, header: string | undefin
|
|
|
75
75
|
* @returns an `mcpServers` fragment accepted by most MCP clients.
|
|
76
76
|
*/
|
|
77
77
|
export declare function clientConfig(url: string, token: string): ClientConfig;
|
|
78
|
+
/** Path of the authenticated config route the Settings page reads. */
|
|
79
|
+
export declare const CONFIG_ROUTE_PATH = "/api/dsh-session-mcp/config";
|
|
80
|
+
/** Every snippet the Settings page offers for copying. */
|
|
81
|
+
export interface ConfigSnippets {
|
|
82
|
+
/** `mcpServers` JSON for Claude Desktop, Cursor and other JSON clients. */
|
|
83
|
+
readonly json: string;
|
|
84
|
+
/** `~/.codex/config.toml` block. */
|
|
85
|
+
readonly codexToml: string;
|
|
86
|
+
/** One `claude mcp add` command. */
|
|
87
|
+
readonly claudeCode: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Render the copy-paste snippets for one endpoint.
|
|
91
|
+
* @param url - full MCP endpoint URL.
|
|
92
|
+
* @param token - bearer token.
|
|
93
|
+
* @returns the three snippets the Settings page shows.
|
|
94
|
+
*/
|
|
95
|
+
export declare function snippetsFor(url: string, token: string): ConfigSnippets;
|
|
96
|
+
/** What the Settings page receives from the Host. */
|
|
97
|
+
export interface ConfigPayload {
|
|
98
|
+
readonly name: string;
|
|
99
|
+
readonly url: string;
|
|
100
|
+
readonly host: string;
|
|
101
|
+
readonly port: number;
|
|
102
|
+
readonly token: string;
|
|
103
|
+
readonly updatedAt: string;
|
|
104
|
+
readonly snippets: ConfigSnippets;
|
|
105
|
+
}
|
package/dist/config.js
CHANGED
|
@@ -120,3 +120,24 @@ export function clientConfig(url, token) {
|
|
|
120
120
|
},
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
|
+
/** Path of the authenticated config route the Settings page reads. */
|
|
124
|
+
export const CONFIG_ROUTE_PATH = '/api/dsh-session-mcp/config';
|
|
125
|
+
/**
|
|
126
|
+
* Render the copy-paste snippets for one endpoint.
|
|
127
|
+
* @param url - full MCP endpoint URL.
|
|
128
|
+
* @param token - bearer token.
|
|
129
|
+
* @returns the three snippets the Settings page shows.
|
|
130
|
+
*/
|
|
131
|
+
export function snippetsFor(url, token) {
|
|
132
|
+
return {
|
|
133
|
+
json: JSON.stringify(clientConfig(url, token), null, 2),
|
|
134
|
+
codexToml: [
|
|
135
|
+
`[mcp_servers.${CLIENT_KEY}]`,
|
|
136
|
+
`url = "${url}"`,
|
|
137
|
+
'',
|
|
138
|
+
`[mcp_servers.${CLIENT_KEY}.http_headers]`,
|
|
139
|
+
`Authorization = "Bearer ${token}"`,
|
|
140
|
+
].join('\n'),
|
|
141
|
+
claudeCode: `claude mcp add --transport http ${CLIENT_KEY} ${url} --header "Authorization: Bearer ${token}"`,
|
|
142
|
+
};
|
|
143
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* @module dsh-session-mcp
|
|
14
14
|
*/
|
|
15
15
|
import { readFileSync } from 'node:fs';
|
|
16
|
-
import { clientConfig, createToken, DEFAULT_HOST, DEFAULT_PORT, readState, SERVER_NAME, writeState, } from './config.js';
|
|
16
|
+
import { clientConfig, CONFIG_ROUTE_PATH, createToken, DEFAULT_HOST, DEFAULT_PORT, readState, SERVER_NAME, snippetsFor, writeState, } from './config.js';
|
|
17
17
|
import { startEndpoint } from './server.js';
|
|
18
18
|
/** Stable Cordis plugin name. */
|
|
19
19
|
export const name = 'dsh-session-mcp';
|
|
@@ -85,6 +85,31 @@ export async function apply(ctx, config) {
|
|
|
85
85
|
ctx.logger?.info?.(`dsh-session-mcp: bearer token and client config in ${file}`);
|
|
86
86
|
console.log(`dsh-session-mcp: ${endpoint.url} (bearer in ${file})`);
|
|
87
87
|
console.log(JSON.stringify(state.client, null, 2));
|
|
88
|
+
// The Settings page reads the live config over the authenticated `/api`
|
|
89
|
+
// channel, so the token never enters the served HTML.
|
|
90
|
+
const payload = {
|
|
91
|
+
name: SERVER_NAME,
|
|
92
|
+
url: endpoint.url,
|
|
93
|
+
host,
|
|
94
|
+
port: endpoint.port,
|
|
95
|
+
token,
|
|
96
|
+
updatedAt: state.updatedAt,
|
|
97
|
+
snippets: snippetsFor(endpoint.url, token),
|
|
98
|
+
};
|
|
99
|
+
ctx.inject(['connection'], (connectionCtx) => {
|
|
100
|
+
connectionCtx.connection.fetch.register({
|
|
101
|
+
path: CONFIG_ROUTE_PATH,
|
|
102
|
+
methods: ['GET'],
|
|
103
|
+
requestBody: 'buffered',
|
|
104
|
+
fetch: async () => new Response(JSON.stringify(payload), {
|
|
105
|
+
status: 200,
|
|
106
|
+
headers: {
|
|
107
|
+
'content-type': 'application/json; charset=utf-8',
|
|
108
|
+
'cache-control': 'no-store',
|
|
109
|
+
},
|
|
110
|
+
}),
|
|
111
|
+
});
|
|
112
|
+
});
|
|
88
113
|
ctx.effect(() => () => {
|
|
89
114
|
void endpoint.close();
|
|
90
115
|
}, 'dsh-session-mcp: endpoint lifetime');
|
package/dist/types.d.ts
CHANGED
|
@@ -79,4 +79,20 @@ export interface PluginContext {
|
|
|
79
79
|
readonly sessionController: SessionController;
|
|
80
80
|
readonly logger?: PluginLogger;
|
|
81
81
|
effect(setup: () => () => void, label?: string): void;
|
|
82
|
+
inject(deps: readonly string[], callback: (ctx: ConnectionContext) => void): void;
|
|
83
|
+
}
|
|
84
|
+
/** One exact Fetch route on the authenticated `/api` channel. */
|
|
85
|
+
export interface FetchRoute {
|
|
86
|
+
readonly path: string;
|
|
87
|
+
readonly methods: readonly string[];
|
|
88
|
+
readonly requestBody: 'buffered' | 'streaming';
|
|
89
|
+
readonly fetch: (request: Request) => Promise<Response>;
|
|
90
|
+
}
|
|
91
|
+
/** The slice of the Client Connection service a Host plugin can use. */
|
|
92
|
+
export interface ConnectionContext {
|
|
93
|
+
readonly connection: {
|
|
94
|
+
readonly fetch: {
|
|
95
|
+
register(route: FetchRoute): unknown;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
82
98
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nones/dsh-session-mcp",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "MCP server for DeepSeek Harness sessions — list, read and prompt live conversations from any MCP client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,7 +45,11 @@
|
|
|
45
45
|
"default": "./dist/config.js"
|
|
46
46
|
},
|
|
47
47
|
"./locale/*.json": "./locale/*.json",
|
|
48
|
-
"./icon": "./icon.svg"
|
|
48
|
+
"./icon": "./icon.svg",
|
|
49
|
+
"./client": {
|
|
50
|
+
"types": "./dist/client.d.ts",
|
|
51
|
+
"default": "./dist/client.js"
|
|
52
|
+
}
|
|
49
53
|
},
|
|
50
54
|
"files": [
|
|
51
55
|
"dist",
|
|
@@ -56,8 +60,8 @@
|
|
|
56
60
|
"LICENSE"
|
|
57
61
|
],
|
|
58
62
|
"scripts": {
|
|
59
|
-
"build": "tsc -p tsconfig.json",
|
|
60
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
63
|
+
"build": "tsc -p tsconfig.json && tsc -p tsconfig.client.json",
|
|
64
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit",
|
|
61
65
|
"prepublishOnly": "npm run build"
|
|
62
66
|
},
|
|
63
67
|
"publishConfig": {
|
|
@@ -76,6 +80,13 @@
|
|
|
76
80
|
"dsh": {
|
|
77
81
|
"bundle": {
|
|
78
82
|
"patch": "./cordis.patch.yml"
|
|
83
|
+
},
|
|
84
|
+
"client": {
|
|
85
|
+
"platform": "web",
|
|
86
|
+
"immediately": true,
|
|
87
|
+
"inject": [
|
|
88
|
+
"@deepseek-ai/dsh-client-ui-settings"
|
|
89
|
+
]
|
|
79
90
|
}
|
|
80
91
|
}
|
|
81
92
|
}
|