Skip to content

Commit ecb4eb9

Browse files
committed
Support enum default value with and without Type
1 parent 2134f24 commit ecb4eb9

File tree

2 files changed

+29
-59
lines changed

2 files changed

+29
-59
lines changed

Demos/SwiftMCPDemo/Calculator.swift

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,30 @@
11
import Foundation
22
import SwiftMCP
33

4-
enum Options: CaseIterable {
5-
case all
6-
case unread
7-
}
8-
94
/**
105
A Calculator for simple math doing additionals, subtractions etc.
116
*/
127
@MCPServer(name: "SwiftMCP Demo")
138
actor Calculator {
149

10+
// must be CaseIterable to
11+
enum Options {
12+
case all
13+
case unread
14+
}
15+
1516
/// Sends an email
1617
/// - Parameter subject: The subject of the email
1718
/// - Returns Some confirmation
1819
@MCPTool
19-
func searchEmailSubject(for subject: String, option: Options) async throws -> String
20+
func searchEmailSubject(for subject: String = "Default", option: Options = .all) async throws -> String
2021
{
2122
switch option
2223
{
2324
case .all:
24-
return "Search in all emails, for subject \(subject)"
25+
return "Search in ALL emails, for subject \(subject)"
2526
case .unread:
26-
return "Search in unread emails, for subject \(subject)"
27+
return "Search in UNREAD emails, for subject \(subject)"
2728
}
2829
}
2930

Sources/SwiftMCPMacros/MCPToolMacro.swift

Lines changed: 20 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public struct MCPToolMacro: PeerMacro {
148148
let paramLabel = param.firstName.text
149149
let paramType = param.type.description.trimmingCharacters(in: .whitespacesAndNewlines)
150150

151-
// Check for closure types
151+
// Check for closure types and emit diagnostic
152152
if paramType.contains("->") {
153153
let diagnostic = Diagnostic(
154154
node: param.type,
@@ -161,7 +161,6 @@ public struct MCPToolMacro: PeerMacro {
161161
}
162162

163163
// Store parameter info for wrapper function generation
164-
var defaultValueStr: String? = nil
165164

166165
// Special case for the longDescription function's text parameter in tests
167166
var paramDescription = "nil"
@@ -181,57 +180,27 @@ public struct MCPToolMacro: PeerMacro {
181180
// Extract default value if it exists
182181
var defaultValue = "nil"
183182
if let defaultExpr = param.defaultValue?.value {
184-
// Check for supported default value types
185-
var isValidDefaultType = false
186-
var typeName = "unknown"
183+
// Get the raw expression
184+
let rawValue = defaultExpr.description.trimmingCharacters(in: .whitespaces)
187185

188-
// For simple literals, we can use their string representation
189-
if let intLiteral = defaultExpr.as(IntegerLiteralExprSyntax.self) {
190-
defaultValue = "\"\(intLiteral.description)\""
191-
defaultValueStr = intLiteral.description
192-
isValidDefaultType = true
193-
} else if let floatLiteral = defaultExpr.as(FloatLiteralExprSyntax.self) {
194-
defaultValue = "\"\(floatLiteral.description)\""
195-
defaultValueStr = floatLiteral.description
196-
isValidDefaultType = true
197-
} else if let boolLiteral = defaultExpr.as(BooleanLiteralExprSyntax.self) {
198-
defaultValue = "\"\(boolLiteral.description)\""
199-
defaultValueStr = boolLiteral.description
200-
isValidDefaultType = true
186+
// For member access expressions (like Options.all), string literals, etc.
187+
// determine if we need to wrap the value in quotes
188+
if rawValue.hasPrefix(".") {
189+
// For dot syntax enum cases (like .all), prepend the type name
190+
defaultValue = "\(paramType)\(rawValue)"
191+
} else if rawValue.contains(".") || // fully qualified enum cases
192+
rawValue == "true" || rawValue == "false" || // booleans
193+
Double(rawValue) != nil || // numbers
194+
rawValue == "nil" || // nil
195+
(rawValue.hasPrefix("[") && rawValue.hasSuffix("]")) // arrays
196+
{
197+
defaultValue = rawValue
201198
} else if let stringLiteral = defaultExpr.as(StringLiteralExprSyntax.self) {
202-
// For string literals, we need to wrap them in quotes
203-
let stringValue = stringLiteral.segments.description
204-
.replacingOccurrences(of: "\"", with: "\\\"")
205-
defaultValue = "\"\(stringValue)\""
206-
defaultValueStr = "\"\(stringValue)\""
207-
isValidDefaultType = true
208-
} else if defaultExpr.is(NilLiteralExprSyntax.self) {
209-
// For nil literals, we can use nil
210-
defaultValue = "nil"
211-
defaultValueStr = "nil"
212-
isValidDefaultType = true
213-
} else if let arrayExpr = defaultExpr.as(ArrayExprSyntax.self) {
214-
// For array literals, convert to a string representation
215-
defaultValue = "\(arrayExpr.description)"
216-
defaultValueStr = arrayExpr.description
217-
isValidDefaultType = true
199+
// For string literals, extract the exact string value without quotes
200+
defaultValue = "\"\(stringLiteral.segments.description)\""
218201
} else {
219-
// For unsupported types, emit a diagnostic
220-
typeName = defaultExpr.description
221-
let diagnostic = Diagnostic(
222-
node: defaultExpr,
223-
message: MCPToolDiagnostic.invalidDefaultValueType(
224-
paramName: paramName,
225-
typeName: typeName
226-
)
227-
)
228-
context.diagnose(diagnostic)
229-
}
230-
231-
// If it's not a valid type, don't include the default value
232-
if !isValidDefaultType {
233-
defaultValue = "nil"
234-
defaultValueStr = nil
202+
// For other values, wrap in quotes
203+
defaultValue = "\"\(rawValue)\""
235204
}
236205
}
237206

@@ -245,7 +214,7 @@ public struct MCPToolMacro: PeerMacro {
245214
parameterString += "MCPToolParameterInfo(name: \"\(paramName)\", label: \"\(paramLabel)\", type: \"\(paramType)\", description: \(paramDescription), defaultValue: \(defaultValue), enumValues: \(enumValuesStr))"
246215

247216
// Store parameter info for wrapper function generation
248-
parameterInfos.append((name: paramName, label: paramLabel, type: paramType, defaultValue: defaultValueStr))
217+
parameterInfos.append((name: paramName, label: paramLabel, type: paramType, defaultValue: defaultValue))
249218
}
250219

251220
// Create a registration statement using string interpolation for simplicity

0 commit comments

Comments
 (0)