@@ -359,54 +359,140 @@ public actor MCPConnectionBridge {
359359 let cachedTables = await MainActor . run {
360360 SchemaService . shared. tables ( for: connectionId)
361361 }
362+
363+ let ( driver, _) = try await resolveDriver ( connectionId)
364+
362365 let tables : [ TableInfo ]
363366 if !cachedTables. isEmpty {
364367 tables = cachedTables
365368 } else {
366- let ( driver, _) = try await resolveDriver ( connectionId)
367369 tables = try await DatabaseManager . shared. trackOperation ( sessionId: connectionId) {
368370 try await driver. fetchTables ( )
369371 }
370372 }
371373
372- let resources = tables. map { table in
373- JsonValue . object ( [
374- " uri " : . string( " tablepro://connection/ \( connectionId. uuidString) /schema/ \( table. name) " ) ,
374+ let limitedTables = Array ( tables. prefix ( 100 ) )
375+
376+ var tableSchemas : [ JsonValue ] = [ ]
377+ for table in limitedTables {
378+ let columns = try await DatabaseManager . shared. trackOperation ( sessionId: connectionId) {
379+ try await driver. fetchColumns ( table: table. name)
380+ }
381+
382+ let jsonCols : [ JsonValue ] = columns. map { col in
383+ . object( [
384+ " name " : . string( col. name) ,
385+ " data_type " : . string( col. dataType) ,
386+ " is_nullable " : . bool( col. isNullable) ,
387+ " is_primary_key " : . bool( col. isPrimaryKey)
388+ ] )
389+ }
390+
391+ tableSchemas. append ( . object( [
375392 " name " : . string( table. name) ,
376- " mimeType " : . string( " application/json " )
377- ] )
393+ " type " : . string( table. type. rawValue) ,
394+ " columns " : . array( jsonCols)
395+ ] ) )
378396 }
379- return . object( [ " resources " : . array( resources) ] )
380- }
381397
382- private func resolveConnection( _ connectionId: UUID ) async throws -> DatabaseConnection {
383- let connection = await MainActor . run {
384- DatabaseManager . shared. connectionState ( connectionId) . connection
398+ var result : [ String : JsonValue ] = [ " tables " : . array( tableSchemas) ]
399+ if tables. count > 100 {
400+ result [ " truncated " ] = . bool( true )
401+ result [ " total_tables " ] = . int( tables. count)
385402 }
386- guard let connection else {
387- throw MCPDataLayerError . notConnected ( connectionId)
403+
404+ return . object( result)
405+ }
406+
407+ func fetchHistoryResource(
408+ connectionId: UUID ,
409+ limit: Int ,
410+ search: String ? ,
411+ dateFilter: String ?
412+ ) async throws -> JsonValue {
413+ let filter : DateFilter
414+ switch dateFilter {
415+ case " today " : filter = . today
416+ case " thisWeek " : filter = . thisWeek
417+ case " thisMonth " : filter = . thisMonth
418+ default : filter = . all
419+ }
420+
421+ let entries = await QueryHistoryManager . shared. fetchHistory (
422+ limit: limit,
423+ connectionId: connectionId,
424+ searchText: search,
425+ dateFilter: filter
426+ )
427+
428+ let jsonEntries : [ JsonValue ] = entries. map { entry in
429+ var obj : [ String : JsonValue ] = [
430+ " id " : . string( entry. id. uuidString) ,
431+ " query " : . string( entry. query) ,
432+ " database_name " : . string( entry. databaseName) ,
433+ " executed_at " : . string( ISO8601DateFormatter ( ) . string ( from: entry. executedAt) ) ,
434+ " execution_time_ms " : . double( entry. executionTime * 1_000 ) ,
435+ " row_count " : . int( entry. rowCount) ,
436+ " was_successful " : . bool( entry. wasSuccessful)
437+ ]
438+ if let errorMsg = entry. errorMessage {
439+ obj [ " error_message " ] = . string( errorMsg)
440+ }
441+ return . object( obj)
388442 }
389- return connection
443+
444+ return . object( [ " history " : . array( jsonEntries) ] )
390445 }
391446
392- private func resolveDriver( _ connectionId: UUID ) async throws -> ( any DatabaseDriver , DatabaseType ) {
393- let state = await MainActor . run {
394- DatabaseManager . shared. connectionState ( connectionId)
447+ private func resolveDriver( _ connectionId: UUID ) async throws -> ( DatabaseDriver , DatabaseType ) {
448+ let pending : DatabaseConnection ? = await MainActor . run {
449+ switch DatabaseManager . shared. connectionState ( connectionId) {
450+ case . live: return nil
451+ case . stored( let connection) : return connection
452+ case . unknown: return nil
453+ }
395454 }
396- guard let connection = state . connection else {
397- throw MCPDataLayerError . notConnected ( connectionId )
455+ if let pending {
456+ try await connectIfNeeded ( pending )
398457 }
399- guard let session = state. session, let driver = session. driver else {
400- throw MCPDataLayerError . notConnected ( connectionId)
458+ return try await MainActor . run {
459+ switch DatabaseManager . shared. connectionState ( connectionId) {
460+ case . live( let driver, let session) :
461+ return ( driver, session. connection. type)
462+ case . stored, . unknown:
463+ throw MCPDataLayerError . notConnected ( connectionId)
464+ }
465+ }
466+ }
467+
468+ private func connectIfNeeded( _ connection: DatabaseConnection ) async throws {
469+ try await DatabaseManager . shared. ensureConnected ( connection)
470+ }
471+
472+ private func resolveSession( _ connectionId: UUID ) async throws -> ConnectionSession {
473+ try await MainActor . run {
474+ guard let session = DatabaseManager . shared. activeSessions [ connectionId] else {
475+ throw MCPDataLayerError . notConnected ( connectionId)
476+ }
477+ return session
478+ }
479+ }
480+
481+ private func resolveConnection( _ connectionId: UUID ) async throws -> DatabaseConnection {
482+ try await MainActor . run {
483+ let connections = ConnectionStorage . shared. loadConnections ( )
484+ guard let connection = connections. first ( where: { $0. id == connectionId } ) else {
485+ throw MCPDataLayerError . invalidArgument ( " Connection not found: \( connectionId) " )
486+ }
487+ return connection
401488 }
402- return ( driver, connection. type)
403489 }
404490
405- private static func stripTrailingSemicolons( _ sql : String ) -> String {
406- var result = sql . trimmingCharacters ( in: . whitespacesAndNewlines)
491+ static func stripTrailingSemicolons( _ query : String ) -> String {
492+ var result = query . trimmingCharacters ( in: . whitespacesAndNewlines)
407493 while result. hasSuffix ( " ; " ) {
408- result. removeLast ( )
409- result = result . trimmingCharacters ( in: . whitespacesAndNewlines)
494+ result = String ( result . dropLast ( ) )
495+ . trimmingCharacters ( in: . whitespacesAndNewlines)
410496 }
411497 return result
412498 }
0 commit comments