Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 31 additions & 28 deletions packages/darklang/languageTools/mcp-server/initialize.dark
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,43 @@ let handleInitializeRequest
: McpState =
log "Handling initialize request"

// Build server capabilities
// Build server capabilities using proper types
let serverCapabilities =
Json.Object [
("resources", Json.Object [
("subscribe", Json.Bool false);
("listChanged", Json.Bool true)
]);
("tools", Json.Object [
("listChanged", Json.Bool true)
]);
("prompts", Json.Object [
("listChanged", Json.Bool true)
]);
("logging", Json.Object []);
("roots", Json.Object [
("listChanged", Json.Bool true)
])
]
ModelContextProtocol.ServerCapabilities {
resources = Stdlib.Option.Option.Some (ModelContextProtocol.ResourceCapabilities {
listChanged = Stdlib.Option.Option.Some true;
subscribe = Stdlib.Option.Option.Some false
});
tools = Stdlib.Option.Option.Some (ModelContextProtocol.ToolCapabilities {
listChanged = Stdlib.Option.Option.Some true
});
prompts = Stdlib.Option.Option.Some (ModelContextProtocol.PromptCapabilities {
listChanged = Stdlib.Option.Option.Some true
});
logging = Stdlib.Option.Option.Some (Json.Object []);
completions = Stdlib.Option.Option.None;
experimental = Stdlib.Option.Option.None
}

let serverInfo =
Json.Object [
("name", Json.String "Darklang MCP Server");
("version", Json.String "1.0.0")
]
ModelContextProtocol.ServerInfo {
name = "Darklang MCP Server";
version = "1.0.0"
}

let result =
Json.Object [
("protocolVersion", Json.String "2025-06-18");
("capabilities", serverCapabilities);
("serverInfo", serverInfo)
]
let initializeResult =
ModelContextProtocol.LifeCycle.InitializeRequest.InitializeResult.InitializeResult {
protocolVersion = ModelContextProtocol.protocolVersion;
serverInfo = serverInfo;
capabilities = serverCapabilities;
instructions = Stdlib.Option.Option.None
}

// Convert to JSON using the typed approach
let resultJson = ModelContextProtocol.LifeCycle.InitializeRequest.InitializeResult.toJson initializeResult

// Send the response
sendSuccessResponse (Stdlib.Option.Option.Some requestId) result
sendSuccessResponse (Stdlib.Option.Option.Some requestId) resultJson

// Return initialized state with all capabilities loaded
let state = initialState ()
Expand Down
59 changes: 39 additions & 20 deletions packages/darklang/languageTools/mcp-server/promptHandlers.dark
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,47 @@ let handleListPromptsRequest
log "Handling prompts/list request"

let promptsList = state.prompts |> Stdlib.Dict.values
let result = Json.Object [
("prompts", Json.Array (promptsList |> Stdlib.List.map (fun prompt ->
Json.Object [
("name", Json.String prompt.name);
("description", Stdlib.Option.mapWithDefault prompt.description Json.Null (fun s -> Json.String s));
("arguments",
match prompt.arguments with
| Some args ->
Json.Array (args |> Stdlib.List.map (fun arg ->
Json.Object [
("name", Json.String arg.name);
("description", Stdlib.Option.mapWithDefault arg.description Json.Null (fun s -> Json.String s));
("required", Stdlib.Option.mapWithDefault arg.required Json.Null (fun b -> Json.Bool b))
]))
| None -> Json.Array []

log "A"

// Convert internal prompt format to MCP PromptDescription
let mcpPrompts = promptsList |> Stdlib.List.map (fun prompt ->
let mcpArguments =
match prompt.arguments with
| Some args ->
let convertedArgs = args |> Stdlib.List.map (fun arg ->
ModelContextProtocol.Prompts.PromptArgument.PromptArgument {
name = arg.name;
description = arg.description;
required = arg.required
}
)
]
)));
("nextCursor", Json.String "")
]
Stdlib.Option.Option.Some convertedArgs
| None -> Stdlib.Option.Option.None

ModelContextProtocol.Prompts.PromptDescription.PromptDescription {
name = prompt.name;
description = prompt.description;
arguments = mcpArguments
}
)
log "B"

let listResult =
ModelContextProtocol.Prompts.ListPromptsResponse.ListPromptsResult {
prompts = mcpPrompts;
nextCursor = Stdlib.Option.Option.None
}

log "C"
Builtin.debug "c" listResult


let resultJson = ModelContextProtocol.Prompts.ListPromptsResponse.toJson listResult

log "D"

sendSuccessResponse (Stdlib.Option.Option.Some requestId) result
sendSuccessResponse (Stdlib.Option.Option.Some requestId) resultJson
state

/// Handle a prompts/get request
Expand Down
30 changes: 18 additions & 12 deletions packages/darklang/languageTools/mcp-server/resourceHandlers.dark
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,25 @@ let handleListResourcesRequest

let resourcesList = state.resources |> Stdlib.Dict.values

let response = Json.Object [
("resources", Json.Array (resourcesList |> Stdlib.List.map (fun resource ->
Json.Object [
("uri", Json.String resource.uri);
("name", Json.String resource.name);
("description", Stdlib.Option.mapWithDefault resource.description Json.Null (fun s -> Json.String s));
("mimeType", Stdlib.Option.mapWithDefault resource.mimeType Json.Null (fun s -> Json.String s))
]
)));
("nextCursor", Json.String "")
]
// Convert internal resource format to MCP ResourceDescription
let mcpResources = resourcesList |> Stdlib.List.map (fun resource ->
ModelContextProtocol.Resources.ListResourcesResponse.ResourceDescription {
uri = resource.uri;
name = resource.name;
description = resource.description;
mimeType = resource.mimeType
}
)

let listResponse =
ModelContextProtocol.Resources.ListResourcesResponse.ListResourcesResponse {
resources = mcpResources;
nextCursor = Stdlib.Option.Option.None
}

let responseJson = ModelContextProtocol.Resources.ListResourcesResponse.toJson listResponse

sendSuccessResponse (Stdlib.Option.Option.Some requestId) response
sendSuccessResponse (Stdlib.Option.Option.Some requestId) responseJson
state

/// Handle a resources/read request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,8 @@ let handleToolCall (args: Json) : Json =
| _ -> ""
| _ -> ""

// In a real implementation, this would search actual functions
let results = [
"Stdlib.List.map - Transform each element of a list";
"Stdlib.String.split - Split a string by delimiter";
"Stdlib.Dict.get - Get a value from a dictionary";
"Builtin.printLine - Print a line to stdout"
]

let resultsText =
$"Search results for '{query}':\n{Stdlib.String.join results "\n"}"
// Simple hardcoded results for now
let resultsText = $"Found 4 functions matching '{query}'"

(ModelContextProtocol.Tools.CallToolResponse.CallToolResult {
content = [
Expand Down
20 changes: 6 additions & 14 deletions packages/darklang/modelContextProtocol/common.dark
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ type GetPromptResult =

/// Prompt capabilities
type PromptCapabilities =
{ supportsPromptListing: Bool
listChanged: Stdlib.Option.Option<Bool> }
{ listChanged: Stdlib.Option.Option<Bool> }

/// Server information
type ServerInfo =
Expand All @@ -128,26 +127,19 @@ type ServerCapabilities =
{ resources: Stdlib.Option.Option<ResourceCapabilities>
tools: Stdlib.Option.Option<ToolCapabilities>
prompts: Stdlib.Option.Option<PromptCapabilities>
logging: Stdlib.Option.Option<LoggingCapabilities>
completion: Stdlib.Option.Option<CompletionCapabilities> }
logging: Stdlib.Option.Option<Json>
completions: Stdlib.Option.Option<Json>
experimental: Stdlib.Option.Option<Dict<Json>> }

/// Resource capabilities
type ResourceCapabilities =
{ supportsResourceListing: Bool
supportsResourceTemplates: Bool }
{ listChanged: Stdlib.Option.Option<Bool>
subscribe: Stdlib.Option.Option<Bool> }

/// Tool capabilities
type ToolCapabilities =
{ listChanged: Stdlib.Option.Option<Bool> }

/// Logging capabilities
type LoggingCapabilities =
{ level: Stdlib.Option.Option<LoggingLevel> }

/// Completion capabilities
type CompletionCapabilities =
{ supportsCompletion: Bool }

/// Error codes for the Model Context Protocol
module ErrorCodes =
let parseError = -32700L
Expand Down
Loading