-
Notifications
You must be signed in to change notification settings - Fork 1.4k
MCP SDK: SDK internal logging & customizable logger #1034
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
KKonstantinov
wants to merge
12
commits into
modelcontextprotocol:main
Choose a base branch
from
KKonstantinov:feature/sdk-internal-logging
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
2042afd
add sdk internal logging PoC
KKonstantinov a78b866
fix comment
KKonstantinov d216768
fix comment
KKonstantinov 7521991
fix comment
KKonstantinov 3d7aca7
prettier
KKonstantinov df2bc7a
Merge branch 'main' into feature/sdk-internal-logging
KKonstantinov cb948fb
refactor to use syslog numbering of severity
KKonstantinov c513241
Merge branch 'feature/sdk-internal-logging' of github.com:KKonstantin…
KKonstantinov 92b9c3c
prettier
KKonstantinov 9f3cdf8
Merge branch 'main' into feature/sdk-internal-logging
KKonstantinov f661a22
Merge branch 'main' of github.com:modelcontextprotocol/typescript-sdk…
KKonstantinov 0ab3a3f
Merge branch 'feature/sdk-internal-logging' of github.com:KKonstantin…
KKonstantinov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| /** | ||
| * LogLevel - SysLog RFC5424 compliant log levels | ||
| * | ||
| * @see RFC5424: https://tools.ietf.org/html/rfc5424 | ||
| */ | ||
| export interface LogLevels { | ||
| emerg: number; | ||
| alert: number; | ||
| crit: number; | ||
| error: number; | ||
| warning: number; | ||
| notice: number; | ||
| info: number; | ||
| debug: number; | ||
| } | ||
|
|
||
| export const LogLevels: LogLevels = { | ||
| emerg: 0, | ||
| alert: 1, | ||
| crit: 2, | ||
| error: 3, | ||
| warning: 4, | ||
| notice: 5, | ||
| info: 6, | ||
| debug: 7 | ||
| }; | ||
|
|
||
| /** | ||
| * Logger - SysLog RFC5424 compliant logger type | ||
| * | ||
| * @see RFC5424: https://tools.ietf.org/html/rfc5424 | ||
| */ | ||
| export type Logger = { | ||
| [Level in keyof LogLevels]: (message: string, extra?: Record<string, unknown>) => void; | ||
| }; | ||
|
|
||
| /** | ||
| * Console logger implementation of the Logger interface, to be used by default if no custom logger is provided. | ||
| * | ||
| * @remarks | ||
| * The console logger will log to the console. | ||
| * | ||
| * The console logger will log at the following levels: | ||
| * - log (alias for console.debug) | ||
| * - info | ||
| * - error | ||
| */ | ||
| export const consoleLogger: Logger = { | ||
| debug: (message, extra) => { | ||
| console.log(message, extra); | ||
| }, | ||
| info: (message, extra) => { | ||
| console.info(message, extra); | ||
| }, | ||
| notice: (message, extra) => { | ||
| console.info(message, extra); | ||
| }, | ||
| warning: (message, extra) => { | ||
| console.warn(message, extra); | ||
| }, | ||
| error: (message, extra) => { | ||
| console.error(message, extra); | ||
| }, | ||
| crit: (message, extra) => { | ||
| console.error(message, extra); | ||
| }, | ||
| alert: (message, extra) => { | ||
| console.error(message, extra); | ||
| }, | ||
| emerg: (message, extra) => { | ||
| console.error(message, extra); | ||
| } | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm concerned about any implementation that uses anything but
console.error, since it will not play well with an STDIO connection, where all messages written to stdout MUST be well-formed JSON-RPC.In Node,
console.log,console.info, andconsole.debugall write tostdout.People might use it only during development and with StreamableHttp it's not an issue, but still, it's a footgun.
I could imagine an implementation that always uses
console.error(), but encodes the level name in the message, e.g.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we have another default logger for STDIO specifically? That's absolutely possible, and won't add much overhead in terms of code implementation.
Not sure here... Because otherwise we limit every other transport to .error; I know for sure some systems (e.g. if it's a NextJS backend) will treat .error in a special way - so defaulting for that for info/debug/notice seems suspicious.
Alternatively, we can wholeheartedly just export the default console logger, a default stdio console logger, and let the end user of the SDK specify it if they wish. Otherwise, our default would be to not log anything?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing two logger implementations, one that would work with STDIO and one that would work with other transports seems reasonable. Not sure how to name them, maybe
defaultLoggerandstdioLogger? ThenstreamableHttp.tscould usedefaultLoggerandstdio.tscould usestdioLogger.However, you were planning to log in different places in the SDK, will they all have access to the logger that the transport has chosen? Server code that gets run before a transport is connected could still fail. What logger would it use? Maybe when creating a
ServerorMcpServerinstance, you could pass it in there? Since you havelogger:LoggerinProtocolOptions, and sinceServerOptionsextendsProtocolOptionsyou should be able to send it in when creating the server:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem I see is that McpServer might then use a
defaultLogger, then upon connecting to Stdio, we could switch tostdioLogger(for that, we can use botherrorandwarnsince they both get written tostderras opposed tostdout).However, it still concerns me - I'm not sure if
McpServerwrote tostdoutjust before theStdioServerTransportgot connected, whether that would cause issues for stdio? I need to check/test.Ultimately we might decide to not go for a default logger at all, and leave that to the implementor? Or alternatively, only have default for the HTTP transports?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking the exact same thing, re: logging to
stdiofrom the server prior to connection and thenstderrfrom connection onward. I sort of think that would be ok. We'd want to make sure that the logger used prior to connection is replaced by the logger used afterward. That is,Serverclass would have a public logger property that could be set by theMcpServerclass and replaced once theTransportimplementation once connected.McpServerwould use the logger on itsthis.serverreference, or better, by way of accessors to such. So