Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Ean Schuessler
/
mo-mcp
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
d8ffaac1
authored
2025-12-30 10:37:19 -0600
by
Ean Schuessler
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Fix duplicate field declarations in EnhancedMcpServlet
1 parent
8489faad
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
29 additions
and
18 deletions
src/main/groovy/org/moqui/mcp/EnhancedMcpServlet.groovy
src/main/groovy/org/moqui/mcp/EnhancedMcpServlet.groovy
View file @
d8ffaac
...
...
@@ -58,20 +58,17 @@ class EnhancedMcpServlet extends HttpServlet {
// No need for separate session manager - Visit entity handles persistence
private
final
Map
<
String
,
Integer
>
sessionStates
=
new
ConcurrentHashMap
<>()
// Progress tracking for notifications/progress
private
final
Map
<
String
,
Map
>
sessionProgress
=
new
ConcurrentHashMap
<>()
// Visit cache to reduce database access and prevent lock contention
private
final
Map
<
String
,
EntityValue
>
visitCache
=
new
ConcurrentHashMap
<>()
// Message storage for notifications/subscribe and notifications/unsubscribe
private
final
Map
<
String
,
List
<
Map
>>
sessionMessages
=
new
ConcurrentHashMap
<>()
// In-memory session tracking to avoid database access for read operations
private
final
Map
<
String
,
String
>
sessionUsers
=
new
ConcurrentHashMap
<>()
//
Message storage for notifications/message
private
final
Map
<
String
,
List
<
Map
>>
sessionMessage
s
=
new
ConcurrentHashMap
<>()
//
Progress tracking for notifications/progress
private
final
Map
<
String
,
Map
>
sessionProgres
s
=
new
ConcurrentHashMap
<>()
//
Subscription tracking for notifications/subscribe and notifications/unsubscribe
private
final
Map
<
String
,
Set
<
String
>>
sessionSubscriptions
=
new
ConcurrentHashMap
<>()
//
Visit cache to reduce database access and prevent lock contention
private
final
Map
<
String
,
EntityValue
>
visitCache
=
new
ConcurrentHashMap
<>()
// Notification queue for server-initiated notifications (for non-SSE clients)
private
static
final
Map
<
String
,
List
<
Map
>>
notificationQueues
=
new
ConcurrentHashMap
<>()
...
...
@@ -511,18 +508,32 @@ class EnhancedMcpServlet extends HttpServlet {
private
void
handleJsonRpc
(
HttpServletRequest
request
,
HttpServletResponse
response
,
ExecutionContextImpl
ec
,
String
webappName
,
String
requestBody
,
def
visit
)
throws
IOException
{
// Initialize web facade for proper session management (like SSE connections)
// This prevents the null user loop by ensuring HTTP session is properly linked
// Initialize web facade for proper session management
try
{
// If we have a visit, make sure it's in the request/session before initWebFacade
// If we have a visit, use it directly (don't create new one)
visit
=
ec
.
user
.
getVisit
()
if
(
visit
)
{
request
.
setAttribute
(
"moqui.visitId"
,
visit
.
visitId
)
request
.
getSession
().
setAttribute
(
"moqui.visitId"
,
visit
.
visitId
)
logger
.
debug
(
"JSON-RPC web facade initialized for user: ${ec.user?.username} with visit: ${visit.visitId}"
)
}
else
{
// No visit exists, need to create one
logger
.
info
(
"Creating new Visit record for user: ${ec.user?.username}"
)
visit
=
ec
.
entity
.
makeValue
(
"moqui.server.Visit"
)
visit
.
visitId
=
ec
.
userFacade
.
getVisitId
(
visit
)
visit
.
userId
=
ec
.
user
.
userId
visit
.
sessionId
=
visit
.
sessionId
visit
.
userAccountId
=
ec
.
user
.
userAccount
?.
userAccountId
visit
.
sessionCreatedDate
=
ec
.
user
.
nowTimestamp
visit
.
visitStatus
=
null
visit
.
lastActiveDate
=
ec
.
user
.
nowTimestamp
visit
.
visitDeletedDate
=
null
ec
.
entity
.
create
(
visit
)
logger
.
info
(
"Visit ${visit.visitId} created for user: ${ec.user?.username}"
)
}
ec
.
initWebFacade
(
webappName
,
request
,
response
)
logger
.
debug
(
"JSON-RPC web facade initialized for user: ${ec.user?.username} with visit: ${
ec.user
.visitId}"
)
logger
.
debug
(
"JSON-RPC web facade initialized for user: ${ec.user?.username} with visit: ${
visit
.visitId}"
)
}
catch
(
Exception
e
)
{
logger
.
warn
(
"
JSON-RPC web facade initialization failed
: ${e.message}"
)
logger
.
warn
(
"
Web facade initialization warning
: ${e.message}"
)
// Continue anyway - we may still have basic user context from auth
}
...
...
@@ -532,13 +543,13 @@ class EnhancedMcpServlet extends HttpServlet {
logger
.
info
(
"Enhanced MCP JSON-RPC Request: ${method} ${request.requestURI} - Accept: ${acceptHeader}"
)
// Validate Accept header per MCP 2025-11-25 spec requirement #2
// Client MUST include Accept header with
either
application/json or text/event-stream
if
(!
acceptHeader
||
!
(
acceptHeader
.
contains
(
"application/json"
)
||
acceptHeader
.
contains
(
"text/event-stream"
)
))
{
// Client MUST include Accept header with
at least one of:
application/json or text/event-stream
if
(!
acceptHeader
||
!
acceptHeader
.
contains
(
"application/json"
)
&&
!
acceptHeader
.
contains
(
"text/event-stream"
))
{
response
.
setStatus
(
HttpServletResponse
.
SC_BAD_REQUEST
)
response
.
setContentType
(
"application/json"
)
response
.
writer
.
write
(
JsonOutput
.
toJson
([
jsonrpc:
"2.0"
,
error:
[
code:
-
32600
,
message:
"Accept header must include application/json
and
text/event-stream"
],
error:
[
code:
-
32600
,
message:
"Accept header must include application/json
or
text/event-stream"
],
id:
null
]))
return
...
...
Please
register
or
sign in
to post a comment