{"record":{"id":"8c50044fce662ec5","repo":"dapr/dapr","slug":"unknown-mcp-workflow-name-q-missing-method-segme","errorCode":null,"errorMessage":"unknown MCP workflow name %q: missing method segment","messagePattern":"unknown MCP workflow name %q: missing method segment","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runtime/wfengine/inprocess/mcp/v1/worker.go","lineNumber":185,"sourceCode":"\t\tcursor = result.NextCursor\n\t}\n\treturn nil, fmt.Errorf(\"MCP server returned more than %d pages of tools — refusing to truncate\", maxListToolsPages)\n}\n\n// mcpWorkflowName is a parsed dapr.internal.mcp.<server>.<method>[.<tool>].\ntype mcpWorkflowName struct {\n\tmethod string\n\ttool   string // CallTool only\n}\n\nfunc parseMCPWorkflowName(name string) (mcpWorkflowName, error) {\n\tif !strings.HasPrefix(name, mcpnames.MCPWorkflowPrefix) {\n\t\treturn mcpWorkflowName{}, fmt.Errorf(\"unknown MCP workflow name %q: expected prefix %q\",\n\t\t\tname, mcpnames.MCPWorkflowPrefix)\n\t}\n\tparts := strings.Split(name[len(mcpnames.MCPWorkflowPrefix):], \".\")\n\tif len(parts) < 2 {\n\t\treturn mcpWorkflowName{}, fmt.Errorf(\"unknown MCP workflow name %q: missing method segment\", name)\n\t}\n\tswitch {\n\tcase parts[1] == mcpnames.MCPMethodListTools && len(parts) == 2:\n\t\treturn mcpWorkflowName{method: mcpnames.MCPMethodListTools}, nil\n\tcase parts[1] == mcpnames.MCPMethodCallTool && len(parts) == 3:\n\t\treturn mcpWorkflowName{method: mcpnames.MCPMethodCallTool, tool: parts[2]}, nil\n\tdefault:\n\t\treturn mcpWorkflowName{}, fmt.Errorf(\"unknown MCP workflow name %q: expected method %q or %q\",\n\t\t\tname, mcpnames.MCPMethodListTools, mcpnames.MCPMethodCallTool)\n\t}\n}\n\n// listToolsWorkflow: beforeListTools -> list-tools activity -> afterListTools.\nfunc listToolsWorkflow(ctx *task.WorkflowContext, server *mcpserverapi.MCPServer, serverName string) (any, error) {\n\tif err := runBeforeListTools(ctx, server, serverName); err != nil {\n\t\treturn nil, fmt.Errorf(\"beforeListTools failed: %w\", err)\n\t}\n\tvar result mcp.ListToolsResult","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/dapr/dapr/blob/74ad41702745709bb15fe2114ff693b8c59bc3cc/pkg/runtime/wfengine/inprocess/mcp/v1/worker.go#L167-L203","documentation":"Thrown by parseMCPWorkflowName when the name carries the dapr.internal.mcp. prefix but splits into fewer than two dot-separated segments — i.e. a server name with no method segment. Valid names are dapr.internal.mcp.<server>.<method>[.<tool>]; a bare dapr.internal.mcp.<server> (or an empty remainder from a trailing-dot prefix) leaves parts like [<server>] with no parts[1] method.","triggerScenarios":"Constructing/registering a name such as dapr.internal.mcp.myserver (no ListTools/CallTool segment); a server name containing characters that collapse the split (e.g. the name ending right after the server segment); hand-assembled names that forget the method segment.","commonSituations":"Custom tooling or tests building names by template without the method; refactors that moved the prefix constant to include/exclude a trailing dot; server names empty after manifest validation gaps.","solutions":["Always build names with mcpnames.MCPListToolsWorkflowName/MCPCallToolWorkflowName rather than templates","If hand-building, follow the exact shape dapr.internal.mcp.<server>.<method>[.<tool>] and assert the method is present","Reject MCPServer manifest names that are empty or contain the reserved prefix shape early, at admission","Add a unit test that every registered name parses (prefix, >=2 segments, known method)"],"exampleFix":"// before\nname := fmt.Sprintf(\"%s%s\", mcpnames.MCPWorkflowPrefix, serverName) // no method\n\n// after\nname := mcpnames.MCPListToolsWorkflowName(serverName)","handlingStrategy":"type-guard","validationCode":"// Validate names before registering\nrest := name[len(mcpnames.MCPWorkflowPrefix):]\nif len(strings.Split(rest, \".\")) < 2 {\n    return fmt.Errorf(\"workflow name %q lacks a method segment\", name)\n}","typeGuard":"func hasMethodSegment(name string) bool {\n    if !strings.HasPrefix(name, mcpnames.MCPWorkflowPrefix) { return false }\n    return len(strings.Split(name[len(mcpnames.MCPWorkflowPrefix):], \".\")) >= 2\n}","tryCatchPattern":"parsed, err := parseMCPWorkflowName(name)\nif err != nil {\n    return nil, fmt.Errorf(\"registration bug: %w\", err)\n}","preventionTips":["Always append the method segment when composing names; prefer the mcpnames helpers","Validate MCPServer names are non-empty at admission","Cover name shapes in parser unit tests"],"tags":["workflow","naming","internal","validation"],"backgroundTag":null,"analyzedSha":"74ad41702745709bb15fe2114ff693b8c59bc3cc","analyzedAt":"2026-08-16T04:22:26.543Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}