1
>
/*---------------------------------------------------------------------------------------------
mcpSamplingLog.ts
2
>
* Copyright (c) Microsoft Corporation. All rights reserved.
3
>
* Licensed under the MIT License. See License.txt in the project root for license information.
4
>
*--------------------------------------------------------------------------------------------*/
5
>
6
>
import { Disposable } from '../../../../base/common/lifecycle.js';
7
>
import { localize } from '../../../../nls.js';
8
>
import { ObservableMemento, observableMemento } from '../../../../platform/observable/common/observableMemento.js';
9
>
import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
10
>
import { IMcpServer } from './mcpTypes.js';
11
>
import { MCP } from './modelContextProtocol.js';
12
>
13
>
const enum Constants {
14
>
SamplingRetentionDays = 7,
15
>
MsPerDay = 24 * 60 * 60 * 1000,
16
>
SamplingRetentionMs = SamplingRetentionDays * MsPerDay,
17
>
SamplingLastNMessage = 30,
18
>
}
19
>
20
>
export interface ISamplingStoredData {
21
>
// UTC day ordinal of the first bin in the bins
22
>
head: number;
23
>
// Requests per day, max length of `Constants.SamplingRetentionDays`
24
>
bins: number[];
25
>
// Last sampling requests/responses
26
>
lastReqs: { request: MCP.SamplingMessage[]; response: string; at: number; model: string }[];
27
>
}
28
>
29
>
const samplingMemento = observableMemento<ReadonlyMap<string, ISamplingStoredData>>({
30
>
defaultValue: new Map(),
31
>
key: 'mcp.sampling.logs',
32
>
toStorage: v => JSON.stringify(Array.from(v.entries())),
33
>
fromStorage: v => new Map(JSON.parse(v)),
34
>
});
35
>
36
>
export class McpSamplingLog extends Disposable {
37
>
private readonly _logs: { [K in StorageScope]?: ObservableMemento<ReadonlyMap<string, ISamplingStoredData>> } = {};
38
>
39
>
constructor(
40
>
@IStorageService private readonly _storageService: IStorageService,
41
>
) {
42
>
super();
43
>
}
44
>
45
>
public has(server: IMcpServer): boolean {
46
const storage = this._getLogStorageForServer(server);
47
return storage.get().has(server.definition.id);
48
}
50
>
public get(server: IMcpServer): Readonly<ISamplingStoredData | undefined> {
51
const storage = this._getLogStorageForServer(server);
52
return storage.get().get(server.definition.id);
53
}
55
>
public getAsText(server: IMcpServer): string {
56
const storage = this._getLogStorageForServer(server);
57
const record = storage.get().get(server.definition.id);