{"record":{"id":"1a2d264c1e68e819","repo":"NousResearch/hermes-agent","slug":"name-required","errorCode":null,"errorMessage":"Name required","messagePattern":"Name required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"web/src/lib/mcp-server-create.ts","lineNumber":52,"sourceCode":"}\n\nfunction parseEnv(raw: string): Record<string, string> {\n  const env: Record<string, string> = {};\n  for (const rawLine of raw.split(\"\\n\")) {\n    const line = rawLine.trim();\n    if (!line) continue;\n    const separator = line.indexOf(\"=\");\n    if (separator === -1) continue;\n    const key = line.slice(0, separator).trim();\n    const value = line.slice(separator + 1).trim();\n    if (key) env[key] = value;\n  }\n  return env;\n}\n\nexport function buildMcpServerCreate(draft: McpServerDraft): McpServerCreate {\n  const name = draft.name.trim();\n  if (!name) throw new Error(\"Name required\");\n\n  if (draft.transport === \"http\") {\n    const url = draft.url.trim();\n    if (!url) throw new Error(\"URL required\");\n    if (draft.httpAuth === \"header\" && !draft.bearerToken.trim()) {\n      throw new Error(\"Bearer token required\");\n    }\n\n    const server: McpServerCreate = { name, url };\n    if (draft.httpAuth !== \"none\") server.auth = draft.httpAuth;\n    if (draft.httpAuth === \"header\") {\n      server.bearer_token = draft.bearerToken;\n    }\n    return server;\n  }\n\n  const command = draft.command.trim();\n  if (!command) throw new Error(\"Command required\");","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/web/src/lib/mcp-server-create.ts#L34-L70","documentation":"buildMcpServerCreate validates the MCP-server creation draft before sending it to the API. The server name is required and is trimmed before the check; an empty (or whitespace-only) name throws immediately. This is client-side form validation, so it fires before any network call.","triggerScenarios":"Submitting the 'add MCP server' form with an empty name field; passing a draft object constructed with name: '' or name: '   '; test fixtures omitting the name.","commonSituations":"UI allows submit before required fields are filled; programmatic creation scripts that copy a template draft and forget to set the name.","solutions":["Fill in a non-empty name (it becomes the server's registry key) and submit again.","Disable the submit button until draft.name.trim() is non-empty.","In scripts, assert the draft has a trimmed name before calling buildMcpServerCreate."],"exampleFix":"// before\nbuildMcpServerCreate({ ...draft, name: '   ' })\n\n// after\nbuildMcpServerCreate({ ...draft, name: 'github'.trim() })","handlingStrategy":"validation","validationCode":"const draftValid = (d: McpServerDraft) => d.name.trim().length > 0\nif (!draftValid(draft)) {\n  setFieldError('name', 'Name is required')\n  return\n}","typeGuard":"function hasMcpName(d: McpServerDraft): boolean {\n  return d.name.trim().length > 0\n}","tryCatchPattern":"try {\n  const payload = buildMcpServerCreate(draft)\n} catch (err) {\n  if (String(err) === 'Name required') { focusField('name'); return }\n  throw err\n}","preventionTips":["Disable submit until all transport-required fields are non-empty after trim.","Validate on blur, not only on submit.","Trim inputs at the controlled-component level."],"tags":["validation","mcp","form"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}